10b57cec5SDimitry Andric //===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Streams SystemZ assembly language and associated data, in the form of 100b57cec5SDimitry Andric // MCInsts and MCExprs respectively. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "SystemZAsmPrinter.h" 150b57cec5SDimitry Andric #include "MCTargetDesc/SystemZInstPrinter.h" 160b57cec5SDimitry Andric #include "SystemZConstantPoolValue.h" 170b57cec5SDimitry Andric #include "SystemZMCInstLower.h" 180b57cec5SDimitry Andric #include "TargetInfo/SystemZTargetInfo.h" 19480093f4SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 220b57cec5SDimitry Andric #include "llvm/IR/Mangler.h" 230b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 240b57cec5SDimitry Andric #include "llvm/MC/MCInstBuilder.h" 25480093f4SDimitry Andric #include "llvm/MC/MCSectionELF.h" 260b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 27349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric using namespace llvm; 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the 320b57cec5SDimitry Andric // GR64 register operands turned into GR32s. 330b57cec5SDimitry Andric static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) { 340b57cec5SDimitry Andric if (MI->isCompare()) 350b57cec5SDimitry Andric return MCInstBuilder(Opcode) 360b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 370b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()); 380b57cec5SDimitry Andric else 390b57cec5SDimitry Andric return MCInstBuilder(Opcode) 400b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 410b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg())) 420b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()); 430b57cec5SDimitry Andric } 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the 460b57cec5SDimitry Andric // GR64 register operands turned into GRH32s. 470b57cec5SDimitry Andric static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) { 480b57cec5SDimitry Andric if (MI->isCompare()) 490b57cec5SDimitry Andric return MCInstBuilder(Opcode) 500b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 510b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()); 520b57cec5SDimitry Andric else 530b57cec5SDimitry Andric return MCInstBuilder(Opcode) 540b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 550b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg())) 560b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()); 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the 600b57cec5SDimitry Andric // R2 register turned into a GR64. 610b57cec5SDimitry Andric static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) { 620b57cec5SDimitry Andric return MCInstBuilder(Opcode) 630b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 640b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 650b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())) 660b57cec5SDimitry Andric .addImm(MI->getOperand(3).getImm()) 670b57cec5SDimitry Andric .addImm(MI->getOperand(4).getImm()) 680b57cec5SDimitry Andric .addImm(MI->getOperand(5).getImm()); 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) { 720b57cec5SDimitry Andric StringRef Name = "__tls_get_offset"; 730b57cec5SDimitry Andric return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name), 740b57cec5SDimitry Andric MCSymbolRefExpr::VK_PLT, 750b57cec5SDimitry Andric Context); 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) { 790b57cec5SDimitry Andric StringRef Name = "_GLOBAL_OFFSET_TABLE_"; 800b57cec5SDimitry Andric return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name), 810b57cec5SDimitry Andric MCSymbolRefExpr::VK_None, 820b57cec5SDimitry Andric Context); 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric // MI is an instruction that accepts an optional alignment hint, 860b57cec5SDimitry Andric // and which was already lowered to LoweredMI. If the alignment 870b57cec5SDimitry Andric // of the original memory operand is known, update LoweredMI to 880b57cec5SDimitry Andric // an instruction with the corresponding hint set. 890b57cec5SDimitry Andric static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI, 900b57cec5SDimitry Andric unsigned Opcode) { 9181ad6265SDimitry Andric if (MI->memoperands_empty()) 920b57cec5SDimitry Andric return; 9381ad6265SDimitry Andric 9481ad6265SDimitry Andric Align Alignment = Align(16); 9581ad6265SDimitry Andric for (MachineInstr::mmo_iterator MMOI = MI->memoperands_begin(), 9681ad6265SDimitry Andric EE = MI->memoperands_end(); MMOI != EE; ++MMOI) 9781ad6265SDimitry Andric if ((*MMOI)->getAlign() < Alignment) 9881ad6265SDimitry Andric Alignment = (*MMOI)->getAlign(); 9981ad6265SDimitry Andric 1000b57cec5SDimitry Andric unsigned AlignmentHint = 0; 10181ad6265SDimitry Andric if (Alignment >= Align(16)) 1020b57cec5SDimitry Andric AlignmentHint = 4; 10381ad6265SDimitry Andric else if (Alignment >= Align(8)) 1040b57cec5SDimitry Andric AlignmentHint = 3; 1050b57cec5SDimitry Andric if (AlignmentHint == 0) 1060b57cec5SDimitry Andric return; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric LoweredMI.setOpcode(Opcode); 1090b57cec5SDimitry Andric LoweredMI.addOperand(MCOperand::createImm(AlignmentHint)); 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric // MI loads the high part of a vector from memory. Return an instruction 1130b57cec5SDimitry Andric // that uses replicating vector load Opcode to do the same thing. 1140b57cec5SDimitry Andric static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) { 1150b57cec5SDimitry Andric return MCInstBuilder(Opcode) 1160b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 1170b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 1180b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 1190b57cec5SDimitry Andric .addReg(MI->getOperand(3).getReg()); 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric // MI stores the high part of a vector to memory. Return an instruction 1230b57cec5SDimitry Andric // that uses elemental vector store Opcode to do the same thing. 1240b57cec5SDimitry Andric static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) { 1250b57cec5SDimitry Andric return MCInstBuilder(Opcode) 1260b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 1270b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 1280b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 1290b57cec5SDimitry Andric .addReg(MI->getOperand(3).getReg()) 1300b57cec5SDimitry Andric .addImm(0); 1310b57cec5SDimitry Andric } 1320b57cec5SDimitry Andric 13381ad6265SDimitry Andric // The XPLINK ABI requires that a no-op encoding the call type is emitted after 13481ad6265SDimitry Andric // each call to a subroutine. This information can be used by the called 13581ad6265SDimitry Andric // function to determine its entry point, e.g. for generating a backtrace. The 13681ad6265SDimitry Andric // call type is encoded as a register number in the bcr instruction. See 13781ad6265SDimitry Andric // enumeration CallType for the possible values. 13881ad6265SDimitry Andric void SystemZAsmPrinter::emitCallInformation(CallType CT) { 13981ad6265SDimitry Andric EmitToStreamer(*OutStreamer, 14081ad6265SDimitry Andric MCInstBuilder(SystemZ::BCRAsm) 14181ad6265SDimitry Andric .addImm(0) 14281ad6265SDimitry Andric .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)])); 14381ad6265SDimitry Andric } 14481ad6265SDimitry Andric 1455ffd83dbSDimitry Andric void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) { 146*753f127fSDimitry Andric SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(), 147*753f127fSDimitry Andric getSubtargetInfo().getFeatureBits()); 148*753f127fSDimitry Andric 1490b57cec5SDimitry Andric SystemZMCInstLower Lower(MF->getContext(), *this); 1500b57cec5SDimitry Andric MCInst LoweredMI; 1510b57cec5SDimitry Andric switch (MI->getOpcode()) { 1520b57cec5SDimitry Andric case SystemZ::Return: 15381ad6265SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BR) 15481ad6265SDimitry Andric .addReg(SystemZ::R14D); 15581ad6265SDimitry Andric break; 15681ad6265SDimitry Andric 15781ad6265SDimitry Andric case SystemZ::Return_XPLINK: 15881ad6265SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::B) 15981ad6265SDimitry Andric .addReg(SystemZ::R7D) 16081ad6265SDimitry Andric .addImm(2) 16181ad6265SDimitry Andric .addReg(0); 1620b57cec5SDimitry Andric break; 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric case SystemZ::CondReturn: 1650b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BCR) 1660b57cec5SDimitry Andric .addImm(MI->getOperand(0).getImm()) 1670b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 1680b57cec5SDimitry Andric .addReg(SystemZ::R14D); 1690b57cec5SDimitry Andric break; 1700b57cec5SDimitry Andric 17181ad6265SDimitry Andric case SystemZ::CondReturn_XPLINK: 17281ad6265SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BC) 17381ad6265SDimitry Andric .addImm(MI->getOperand(0).getImm()) 17481ad6265SDimitry Andric .addImm(MI->getOperand(1).getImm()) 17581ad6265SDimitry Andric .addReg(SystemZ::R7D) 17681ad6265SDimitry Andric .addImm(2) 17781ad6265SDimitry Andric .addReg(0); 17881ad6265SDimitry Andric break; 17981ad6265SDimitry Andric 1800b57cec5SDimitry Andric case SystemZ::CRBReturn: 1810b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CRB) 1820b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 1830b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 1840b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 1850b57cec5SDimitry Andric .addReg(SystemZ::R14D) 1860b57cec5SDimitry Andric .addImm(0); 1870b57cec5SDimitry Andric break; 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric case SystemZ::CGRBReturn: 1900b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CGRB) 1910b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 1920b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 1930b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 1940b57cec5SDimitry Andric .addReg(SystemZ::R14D) 1950b57cec5SDimitry Andric .addImm(0); 1960b57cec5SDimitry Andric break; 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric case SystemZ::CIBReturn: 1990b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CIB) 2000b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2010b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2020b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2030b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2040b57cec5SDimitry Andric .addImm(0); 2050b57cec5SDimitry Andric break; 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric case SystemZ::CGIBReturn: 2080b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CGIB) 2090b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2100b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2110b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2120b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2130b57cec5SDimitry Andric .addImm(0); 2140b57cec5SDimitry Andric break; 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric case SystemZ::CLRBReturn: 2170b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLRB) 2180b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2190b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 2200b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2210b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2220b57cec5SDimitry Andric .addImm(0); 2230b57cec5SDimitry Andric break; 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric case SystemZ::CLGRBReturn: 2260b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLGRB) 2270b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2280b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 2290b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2300b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2310b57cec5SDimitry Andric .addImm(0); 2320b57cec5SDimitry Andric break; 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric case SystemZ::CLIBReturn: 2350b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLIB) 2360b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2370b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2380b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2390b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2400b57cec5SDimitry Andric .addImm(0); 2410b57cec5SDimitry Andric break; 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric case SystemZ::CLGIBReturn: 2440b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLGIB) 2450b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2460b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2470b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2480b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2490b57cec5SDimitry Andric .addImm(0); 2500b57cec5SDimitry Andric break; 2510b57cec5SDimitry Andric 252fe6060f1SDimitry Andric case SystemZ::CallBRASL_XPLINK64: 253fe6060f1SDimitry Andric EmitToStreamer(*OutStreamer, 254fe6060f1SDimitry Andric MCInstBuilder(SystemZ::BRASL) 255fe6060f1SDimitry Andric .addReg(SystemZ::R7D) 256fe6060f1SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), 257fe6060f1SDimitry Andric MCSymbolRefExpr::VK_PLT))); 25881ad6265SDimitry Andric emitCallInformation(CallType::BRASL7); 259fe6060f1SDimitry Andric return; 260fe6060f1SDimitry Andric 261fe6060f1SDimitry Andric case SystemZ::CallBASR_XPLINK64: 262fe6060f1SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 263fe6060f1SDimitry Andric .addReg(SystemZ::R7D) 264fe6060f1SDimitry Andric .addReg(MI->getOperand(0).getReg())); 26581ad6265SDimitry Andric emitCallInformation(CallType::BASR76); 26681ad6265SDimitry Andric return; 26781ad6265SDimitry Andric 26881ad6265SDimitry Andric case SystemZ::CallBASR_STACKEXT: 26981ad6265SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 27081ad6265SDimitry Andric .addReg(SystemZ::R3D) 27181ad6265SDimitry Andric .addReg(MI->getOperand(0).getReg())); 27281ad6265SDimitry Andric emitCallInformation(CallType::BASR33); 273fe6060f1SDimitry Andric return; 274fe6060f1SDimitry Andric 2750b57cec5SDimitry Andric case SystemZ::CallBRASL: 2760b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRASL) 2770b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2780b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 2790b57cec5SDimitry Andric break; 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric case SystemZ::CallBASR: 2820b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BASR) 2830b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2840b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()); 2850b57cec5SDimitry Andric break; 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric case SystemZ::CallJG: 2880b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::JG) 2890b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 2900b57cec5SDimitry Andric break; 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric case SystemZ::CallBRCL: 2930b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRCL) 2940b57cec5SDimitry Andric .addImm(MI->getOperand(0).getImm()) 2950b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2960b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT)); 2970b57cec5SDimitry Andric break; 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric case SystemZ::CallBR: 300e8d8bef9SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BR) 301e8d8bef9SDimitry Andric .addReg(MI->getOperand(0).getReg()); 3020b57cec5SDimitry Andric break; 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric case SystemZ::CallBCR: 3050b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BCR) 3060b57cec5SDimitry Andric .addImm(MI->getOperand(0).getImm()) 3070b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 308e8d8bef9SDimitry Andric .addReg(MI->getOperand(2).getReg()); 3090b57cec5SDimitry Andric break; 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric case SystemZ::CRBCall: 3120b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CRB) 3130b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3140b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 3150b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 316e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 3170b57cec5SDimitry Andric .addImm(0); 3180b57cec5SDimitry Andric break; 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric case SystemZ::CGRBCall: 3210b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CGRB) 3220b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3230b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 3240b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 325e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 3260b57cec5SDimitry Andric .addImm(0); 3270b57cec5SDimitry Andric break; 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric case SystemZ::CIBCall: 3300b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CIB) 3310b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3320b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 3330b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 334e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 3350b57cec5SDimitry Andric .addImm(0); 3360b57cec5SDimitry Andric break; 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric case SystemZ::CGIBCall: 3390b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CGIB) 3400b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3410b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 3420b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 343e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 3440b57cec5SDimitry Andric .addImm(0); 3450b57cec5SDimitry Andric break; 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric case SystemZ::CLRBCall: 3480b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLRB) 3490b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3500b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 3510b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 352e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 3530b57cec5SDimitry Andric .addImm(0); 3540b57cec5SDimitry Andric break; 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric case SystemZ::CLGRBCall: 3570b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLGRB) 3580b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3590b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 3600b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 361e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 3620b57cec5SDimitry Andric .addImm(0); 3630b57cec5SDimitry Andric break; 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric case SystemZ::CLIBCall: 3660b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLIB) 3670b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3680b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 3690b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 370e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 3710b57cec5SDimitry Andric .addImm(0); 3720b57cec5SDimitry Andric break; 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric case SystemZ::CLGIBCall: 3750b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLGIB) 3760b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3770b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 3780b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 379e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 3800b57cec5SDimitry Andric .addImm(0); 3810b57cec5SDimitry Andric break; 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric case SystemZ::TLS_GDCALL: 3840b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRASL) 3850b57cec5SDimitry Andric .addReg(SystemZ::R14D) 3860b57cec5SDimitry Andric .addExpr(getTLSGetOffset(MF->getContext())) 3870b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD)); 3880b57cec5SDimitry Andric break; 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric case SystemZ::TLS_LDCALL: 3910b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRASL) 3920b57cec5SDimitry Andric .addReg(SystemZ::R14D) 3930b57cec5SDimitry Andric .addExpr(getTLSGetOffset(MF->getContext())) 3940b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM)); 3950b57cec5SDimitry Andric break; 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric case SystemZ::GOT: 3980b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::LARL) 3990b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4000b57cec5SDimitry Andric .addExpr(getGlobalOffsetTable(MF->getContext())); 4010b57cec5SDimitry Andric break; 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric case SystemZ::IILF64: 4040b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::IILF) 4050b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 4060b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()); 4070b57cec5SDimitry Andric break; 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric case SystemZ::IIHF64: 4100b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::IIHF) 4110b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 4120b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()); 4130b57cec5SDimitry Andric break; 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric case SystemZ::RISBHH: 4160b57cec5SDimitry Andric case SystemZ::RISBHL: 4170b57cec5SDimitry Andric LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG); 4180b57cec5SDimitry Andric break; 4190b57cec5SDimitry Andric 4200b57cec5SDimitry Andric case SystemZ::RISBLH: 4210b57cec5SDimitry Andric case SystemZ::RISBLL: 4220b57cec5SDimitry Andric LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG); 4230b57cec5SDimitry Andric break; 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric case SystemZ::VLVGP32: 4260b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::VLVGP) 4270b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4280b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg())) 4290b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())); 4300b57cec5SDimitry Andric break; 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric case SystemZ::VLR32: 4330b57cec5SDimitry Andric case SystemZ::VLR64: 4340b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::VLR) 4350b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 4360b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())); 4370b57cec5SDimitry Andric break; 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric case SystemZ::VL: 4400b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 4410b57cec5SDimitry Andric lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign); 4420b57cec5SDimitry Andric break; 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric case SystemZ::VST: 4450b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 4460b57cec5SDimitry Andric lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign); 4470b57cec5SDimitry Andric break; 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric case SystemZ::VLM: 4500b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 4510b57cec5SDimitry Andric lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign); 4520b57cec5SDimitry Andric break; 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric case SystemZ::VSTM: 4550b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 4560b57cec5SDimitry Andric lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign); 4570b57cec5SDimitry Andric break; 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric case SystemZ::VL32: 4600b57cec5SDimitry Andric LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF); 4610b57cec5SDimitry Andric break; 4620b57cec5SDimitry Andric 4630b57cec5SDimitry Andric case SystemZ::VL64: 4640b57cec5SDimitry Andric LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG); 4650b57cec5SDimitry Andric break; 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric case SystemZ::VST32: 4680b57cec5SDimitry Andric LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF); 4690b57cec5SDimitry Andric break; 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric case SystemZ::VST64: 4720b57cec5SDimitry Andric LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG); 4730b57cec5SDimitry Andric break; 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric case SystemZ::LFER: 4760b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::VLGVF) 4770b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg())) 4780b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())) 4790b57cec5SDimitry Andric .addReg(0).addImm(0); 4800b57cec5SDimitry Andric break; 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric case SystemZ::LEFR: 4830b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::VLVGF) 4840b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 4850b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 4860b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 4870b57cec5SDimitry Andric .addReg(0).addImm(0); 4880b57cec5SDimitry Andric break; 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric #define LOWER_LOW(NAME) \ 4910b57cec5SDimitry Andric case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break 4920b57cec5SDimitry Andric 4930b57cec5SDimitry Andric LOWER_LOW(IILL); 4940b57cec5SDimitry Andric LOWER_LOW(IILH); 4950b57cec5SDimitry Andric LOWER_LOW(TMLL); 4960b57cec5SDimitry Andric LOWER_LOW(TMLH); 4970b57cec5SDimitry Andric LOWER_LOW(NILL); 4980b57cec5SDimitry Andric LOWER_LOW(NILH); 4990b57cec5SDimitry Andric LOWER_LOW(NILF); 5000b57cec5SDimitry Andric LOWER_LOW(OILL); 5010b57cec5SDimitry Andric LOWER_LOW(OILH); 5020b57cec5SDimitry Andric LOWER_LOW(OILF); 5030b57cec5SDimitry Andric LOWER_LOW(XILF); 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric #undef LOWER_LOW 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric #define LOWER_HIGH(NAME) \ 5080b57cec5SDimitry Andric case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric LOWER_HIGH(IIHL); 5110b57cec5SDimitry Andric LOWER_HIGH(IIHH); 5120b57cec5SDimitry Andric LOWER_HIGH(TMHL); 5130b57cec5SDimitry Andric LOWER_HIGH(TMHH); 5140b57cec5SDimitry Andric LOWER_HIGH(NIHL); 5150b57cec5SDimitry Andric LOWER_HIGH(NIHH); 5160b57cec5SDimitry Andric LOWER_HIGH(NIHF); 5170b57cec5SDimitry Andric LOWER_HIGH(OIHL); 5180b57cec5SDimitry Andric LOWER_HIGH(OIHH); 5190b57cec5SDimitry Andric LOWER_HIGH(OIHF); 5200b57cec5SDimitry Andric LOWER_HIGH(XIHF); 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric #undef LOWER_HIGH 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric case SystemZ::Serialize: 5250b57cec5SDimitry Andric if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization()) 5260b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BCRAsm) 5270b57cec5SDimitry Andric .addImm(14).addReg(SystemZ::R0D); 5280b57cec5SDimitry Andric else 5290b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BCRAsm) 5300b57cec5SDimitry Andric .addImm(15).addReg(SystemZ::R0D); 5310b57cec5SDimitry Andric break; 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric // Emit nothing here but a comment if we can. 5340b57cec5SDimitry Andric case SystemZ::MemBarrier: 5350b57cec5SDimitry Andric OutStreamer->emitRawComment("MEMBARRIER"); 5360b57cec5SDimitry Andric return; 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric // We want to emit "j .+2" for traps, jumping to the relative immediate field 5390b57cec5SDimitry Andric // of the jump instruction, which is an illegal instruction. We cannot emit a 5400b57cec5SDimitry Andric // "." symbol, so create and emit a temp label before the instruction and use 5410b57cec5SDimitry Andric // that instead. 5420b57cec5SDimitry Andric case SystemZ::Trap: { 5430b57cec5SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 5445ffd83dbSDimitry Andric OutStreamer->emitLabel(DotSym); 5450b57cec5SDimitry Andric 5460b57cec5SDimitry Andric const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 5470b57cec5SDimitry Andric const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 5480b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::J) 5490b57cec5SDimitry Andric .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric break; 5520b57cec5SDimitry Andric 5530b57cec5SDimitry Andric // Conditional traps will create a branch on condition instruction that jumps 5540b57cec5SDimitry Andric // to the relative immediate field of the jump instruction. (eg. "jo .+2") 5550b57cec5SDimitry Andric case SystemZ::CondTrap: { 5560b57cec5SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 5575ffd83dbSDimitry Andric OutStreamer->emitLabel(DotSym); 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 5600b57cec5SDimitry Andric const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 5610b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRC) 5620b57cec5SDimitry Andric .addImm(MI->getOperand(0).getImm()) 5630b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 5640b57cec5SDimitry Andric .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 5650b57cec5SDimitry Andric } 5660b57cec5SDimitry Andric break; 5670b57cec5SDimitry Andric 5688bcb0991SDimitry Andric case TargetOpcode::FENTRY_CALL: 5698bcb0991SDimitry Andric LowerFENTRY_CALL(*MI, Lower); 5708bcb0991SDimitry Andric return; 5718bcb0991SDimitry Andric 5720b57cec5SDimitry Andric case TargetOpcode::STACKMAP: 5730b57cec5SDimitry Andric LowerSTACKMAP(*MI); 5740b57cec5SDimitry Andric return; 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric case TargetOpcode::PATCHPOINT: 5770b57cec5SDimitry Andric LowerPATCHPOINT(*MI, Lower); 5780b57cec5SDimitry Andric return; 5790b57cec5SDimitry Andric 580fe6060f1SDimitry Andric case SystemZ::EXRL_Pseudo: { 581fe6060f1SDimitry Andric unsigned TargetInsOpc = MI->getOperand(0).getImm(); 582fe6060f1SDimitry Andric Register LenMinus1Reg = MI->getOperand(1).getReg(); 583fe6060f1SDimitry Andric Register DestReg = MI->getOperand(2).getReg(); 584fe6060f1SDimitry Andric int64_t DestDisp = MI->getOperand(3).getImm(); 585fe6060f1SDimitry Andric Register SrcReg = MI->getOperand(4).getReg(); 586fe6060f1SDimitry Andric int64_t SrcDisp = MI->getOperand(5).getImm(); 587fe6060f1SDimitry Andric 588349cc55cSDimitry Andric SystemZTargetStreamer *TS = getTargetStreamer(); 589fe6060f1SDimitry Andric MCSymbol *DotSym = nullptr; 590fe6060f1SDimitry Andric MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg) 591fe6060f1SDimitry Andric .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp); 592349cc55cSDimitry Andric SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget()); 593349cc55cSDimitry Andric SystemZTargetStreamer::EXRLT2SymMap::iterator I = 594349cc55cSDimitry Andric TS->EXRLTargets2Sym.find(ET_STI); 595349cc55cSDimitry Andric if (I != TS->EXRLTargets2Sym.end()) 596fe6060f1SDimitry Andric DotSym = I->second; 597fe6060f1SDimitry Andric else 598349cc55cSDimitry Andric TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol(); 599fe6060f1SDimitry Andric const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); 600fe6060f1SDimitry Andric EmitToStreamer( 601fe6060f1SDimitry Andric *OutStreamer, 602fe6060f1SDimitry Andric MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot)); 603fe6060f1SDimitry Andric return; 604fe6060f1SDimitry Andric } 605fe6060f1SDimitry Andric 6060b57cec5SDimitry Andric default: 6070b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 6080b57cec5SDimitry Andric break; 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, LoweredMI); 6110b57cec5SDimitry Andric } 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric // Emit the largest nop instruction smaller than or equal to NumBytes 6140b57cec5SDimitry Andric // bytes. Return the size of nop emitted. 6150b57cec5SDimitry Andric static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer, 6160b57cec5SDimitry Andric unsigned NumBytes, const MCSubtargetInfo &STI) { 6170b57cec5SDimitry Andric if (NumBytes < 2) { 6180b57cec5SDimitry Andric llvm_unreachable("Zero nops?"); 6190b57cec5SDimitry Andric return 0; 6200b57cec5SDimitry Andric } 6210b57cec5SDimitry Andric else if (NumBytes < 4) { 6225ffd83dbSDimitry Andric OutStreamer.emitInstruction( 6235ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI); 6240b57cec5SDimitry Andric return 2; 6250b57cec5SDimitry Andric } 6260b57cec5SDimitry Andric else if (NumBytes < 6) { 6275ffd83dbSDimitry Andric OutStreamer.emitInstruction( 6285ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0), 6290b57cec5SDimitry Andric STI); 6300b57cec5SDimitry Andric return 4; 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric else { 6330b57cec5SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 6340b57cec5SDimitry Andric const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); 6355ffd83dbSDimitry Andric OutStreamer.emitLabel(DotSym); 6365ffd83dbSDimitry Andric OutStreamer.emitInstruction( 6375ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI); 6380b57cec5SDimitry Andric return 6; 6390b57cec5SDimitry Andric } 6400b57cec5SDimitry Andric } 6410b57cec5SDimitry Andric 6428bcb0991SDimitry Andric void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI, 6438bcb0991SDimitry Andric SystemZMCInstLower &Lower) { 6448bcb0991SDimitry Andric MCContext &Ctx = MF->getContext(); 645480093f4SDimitry Andric if (MF->getFunction().hasFnAttribute("mrecord-mcount")) { 646480093f4SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 64781ad6265SDimitry Andric OutStreamer->pushSection(); 64881ad6265SDimitry Andric OutStreamer->switchSection( 649480093f4SDimitry Andric Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC)); 6505ffd83dbSDimitry Andric OutStreamer->emitSymbolValue(DotSym, 8); 65181ad6265SDimitry Andric OutStreamer->popSection(); 6525ffd83dbSDimitry Andric OutStreamer->emitLabel(DotSym); 653480093f4SDimitry Andric } 654480093f4SDimitry Andric 655480093f4SDimitry Andric if (MF->getFunction().hasFnAttribute("mnop-mcount")) { 6568bcb0991SDimitry Andric EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo()); 6578bcb0991SDimitry Andric return; 6588bcb0991SDimitry Andric } 6598bcb0991SDimitry Andric 6608bcb0991SDimitry Andric MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__"); 6618bcb0991SDimitry Andric const MCSymbolRefExpr *Op = 6628bcb0991SDimitry Andric MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx); 6635ffd83dbSDimitry Andric OutStreamer->emitInstruction( 6645ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op), 6655ffd83dbSDimitry Andric getSubtargetInfo()); 6668bcb0991SDimitry Andric } 6678bcb0991SDimitry Andric 6680b57cec5SDimitry Andric void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) { 66981ad6265SDimitry Andric auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo(); 6700b57cec5SDimitry Andric 6710b57cec5SDimitry Andric unsigned NumNOPBytes = MI.getOperand(1).getImm(); 6720b57cec5SDimitry Andric 673480093f4SDimitry Andric auto &Ctx = OutStreamer->getContext(); 674480093f4SDimitry Andric MCSymbol *MILabel = Ctx.createTempSymbol(); 6755ffd83dbSDimitry Andric OutStreamer->emitLabel(MILabel); 676480093f4SDimitry Andric 677480093f4SDimitry Andric SM.recordStackMap(*MILabel, MI); 6780b57cec5SDimitry Andric assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!"); 6790b57cec5SDimitry Andric 6800b57cec5SDimitry Andric // Scan ahead to trim the shadow. 6810b57cec5SDimitry Andric unsigned ShadowBytes = 0; 6820b57cec5SDimitry Andric const MachineBasicBlock &MBB = *MI.getParent(); 6830b57cec5SDimitry Andric MachineBasicBlock::const_iterator MII(MI); 6840b57cec5SDimitry Andric ++MII; 6850b57cec5SDimitry Andric while (ShadowBytes < NumNOPBytes) { 6860b57cec5SDimitry Andric if (MII == MBB.end() || 6870b57cec5SDimitry Andric MII->getOpcode() == TargetOpcode::PATCHPOINT || 6880b57cec5SDimitry Andric MII->getOpcode() == TargetOpcode::STACKMAP) 6890b57cec5SDimitry Andric break; 6900b57cec5SDimitry Andric ShadowBytes += TII->getInstSizeInBytes(*MII); 6910b57cec5SDimitry Andric if (MII->isCall()) 6920b57cec5SDimitry Andric break; 6930b57cec5SDimitry Andric ++MII; 6940b57cec5SDimitry Andric } 6950b57cec5SDimitry Andric 6960b57cec5SDimitry Andric // Emit nops. 6970b57cec5SDimitry Andric while (ShadowBytes < NumNOPBytes) 6980b57cec5SDimitry Andric ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes, 6990b57cec5SDimitry Andric getSubtargetInfo()); 7000b57cec5SDimitry Andric } 7010b57cec5SDimitry Andric 7020b57cec5SDimitry Andric // Lower a patchpoint of the form: 7030b57cec5SDimitry Andric // [<def>], <id>, <numBytes>, <target>, <numArgs> 7040b57cec5SDimitry Andric void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI, 7050b57cec5SDimitry Andric SystemZMCInstLower &Lower) { 706480093f4SDimitry Andric auto &Ctx = OutStreamer->getContext(); 707480093f4SDimitry Andric MCSymbol *MILabel = Ctx.createTempSymbol(); 7085ffd83dbSDimitry Andric OutStreamer->emitLabel(MILabel); 709480093f4SDimitry Andric 710480093f4SDimitry Andric SM.recordPatchPoint(*MILabel, MI); 7110b57cec5SDimitry Andric PatchPointOpers Opers(&MI); 7120b57cec5SDimitry Andric 7130b57cec5SDimitry Andric unsigned EncodedBytes = 0; 7140b57cec5SDimitry Andric const MachineOperand &CalleeMO = Opers.getCallTarget(); 7150b57cec5SDimitry Andric 7160b57cec5SDimitry Andric if (CalleeMO.isImm()) { 7170b57cec5SDimitry Andric uint64_t CallTarget = CalleeMO.getImm(); 7180b57cec5SDimitry Andric if (CallTarget) { 7190b57cec5SDimitry Andric unsigned ScratchIdx = -1; 7200b57cec5SDimitry Andric unsigned ScratchReg = 0; 7210b57cec5SDimitry Andric do { 7220b57cec5SDimitry Andric ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1); 7230b57cec5SDimitry Andric ScratchReg = MI.getOperand(ScratchIdx).getReg(); 7240b57cec5SDimitry Andric } while (ScratchReg == SystemZ::R0D); 7250b57cec5SDimitry Andric 7260b57cec5SDimitry Andric // Materialize the call target address 7270b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF) 7280b57cec5SDimitry Andric .addReg(ScratchReg) 7290b57cec5SDimitry Andric .addImm(CallTarget & 0xFFFFFFFF)); 7300b57cec5SDimitry Andric EncodedBytes += 6; 7310b57cec5SDimitry Andric if (CallTarget >> 32) { 7320b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF) 7330b57cec5SDimitry Andric .addReg(ScratchReg) 7340b57cec5SDimitry Andric .addImm(CallTarget >> 32)); 7350b57cec5SDimitry Andric EncodedBytes += 6; 7360b57cec5SDimitry Andric } 7370b57cec5SDimitry Andric 7380b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 7390b57cec5SDimitry Andric .addReg(SystemZ::R14D) 7400b57cec5SDimitry Andric .addReg(ScratchReg)); 7410b57cec5SDimitry Andric EncodedBytes += 2; 7420b57cec5SDimitry Andric } 7430b57cec5SDimitry Andric } else if (CalleeMO.isGlobal()) { 7440b57cec5SDimitry Andric const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT); 7450b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL) 7460b57cec5SDimitry Andric .addReg(SystemZ::R14D) 7470b57cec5SDimitry Andric .addExpr(Expr)); 7480b57cec5SDimitry Andric EncodedBytes += 6; 7490b57cec5SDimitry Andric } 7500b57cec5SDimitry Andric 7510b57cec5SDimitry Andric // Emit padding. 7520b57cec5SDimitry Andric unsigned NumBytes = Opers.getNumPatchBytes(); 7530b57cec5SDimitry Andric assert(NumBytes >= EncodedBytes && 7540b57cec5SDimitry Andric "Patchpoint can't request size less than the length of a call."); 7550b57cec5SDimitry Andric assert((NumBytes - EncodedBytes) % 2 == 0 && 7560b57cec5SDimitry Andric "Invalid number of NOP bytes requested!"); 7570b57cec5SDimitry Andric while (EncodedBytes < NumBytes) 7580b57cec5SDimitry Andric EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes, 7590b57cec5SDimitry Andric getSubtargetInfo()); 7600b57cec5SDimitry Andric } 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric // Convert a SystemZ-specific constant pool modifier into the associated 7630b57cec5SDimitry Andric // MCSymbolRefExpr variant kind. 7640b57cec5SDimitry Andric static MCSymbolRefExpr::VariantKind 7650b57cec5SDimitry Andric getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) { 7660b57cec5SDimitry Andric switch (Modifier) { 7670b57cec5SDimitry Andric case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD; 7680b57cec5SDimitry Andric case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM; 7690b57cec5SDimitry Andric case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF; 7700b57cec5SDimitry Andric case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF; 7710b57cec5SDimitry Andric } 7720b57cec5SDimitry Andric llvm_unreachable("Invalid SystemCPModifier!"); 7730b57cec5SDimitry Andric } 7740b57cec5SDimitry Andric 7755ffd83dbSDimitry Andric void SystemZAsmPrinter::emitMachineConstantPoolValue( 7765ffd83dbSDimitry Andric MachineConstantPoolValue *MCPV) { 7770b57cec5SDimitry Andric auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV); 7780b57cec5SDimitry Andric 7790b57cec5SDimitry Andric const MCExpr *Expr = 7800b57cec5SDimitry Andric MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()), 7810b57cec5SDimitry Andric getModifierVariantKind(ZCPV->getModifier()), 7820b57cec5SDimitry Andric OutContext); 7830b57cec5SDimitry Andric uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType()); 7840b57cec5SDimitry Andric 7855ffd83dbSDimitry Andric OutStreamer->emitValue(Expr, Size); 7860b57cec5SDimitry Andric } 7870b57cec5SDimitry Andric 7880b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 7890b57cec5SDimitry Andric const char *ExtraCode, 7900b57cec5SDimitry Andric raw_ostream &OS) { 791fe6060f1SDimitry Andric const MCRegisterInfo &MRI = *TM.getMCRegisterInfo(); 792fe6060f1SDimitry Andric const MachineOperand &MO = MI->getOperand(OpNo); 793fe6060f1SDimitry Andric MCOperand MCOp; 794fe6060f1SDimitry Andric if (ExtraCode) { 795fe6060f1SDimitry Andric if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() && 796fe6060f1SDimitry Andric SystemZ::GR128BitRegClass.contains(MO.getReg())) 797fe6060f1SDimitry Andric MCOp = 798fe6060f1SDimitry Andric MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64)); 799fe6060f1SDimitry Andric else 8000b57cec5SDimitry Andric return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS); 801fe6060f1SDimitry Andric } else { 8020b57cec5SDimitry Andric SystemZMCInstLower Lower(MF->getContext(), *this); 803fe6060f1SDimitry Andric MCOp = Lower.lowerOperand(MO); 804fe6060f1SDimitry Andric } 805fe6060f1SDimitry Andric SystemZInstPrinter::printOperand(MCOp, MAI, OS); 8060b57cec5SDimitry Andric return false; 8070b57cec5SDimitry Andric } 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 8100b57cec5SDimitry Andric unsigned OpNo, 8110b57cec5SDimitry Andric const char *ExtraCode, 8120b57cec5SDimitry Andric raw_ostream &OS) { 813349cc55cSDimitry Andric SystemZInstPrinter:: 814349cc55cSDimitry Andric printAddress(MAI, MI->getOperand(OpNo).getReg(), 815349cc55cSDimitry Andric MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()), 8160b57cec5SDimitry Andric MI->getOperand(OpNo + 2).getReg(), OS); 8170b57cec5SDimitry Andric return false; 8180b57cec5SDimitry Andric } 8190b57cec5SDimitry Andric 8205ffd83dbSDimitry Andric void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) { 8210b57cec5SDimitry Andric emitStackMaps(SM); 8220b57cec5SDimitry Andric } 8230b57cec5SDimitry Andric 82481ad6265SDimitry Andric void SystemZAsmPrinter::emitFunctionBodyEnd() { 82581ad6265SDimitry Andric if (TM.getTargetTriple().isOSzOS()) { 82681ad6265SDimitry Andric // Emit symbol for the end of function if the z/OS target streamer 82781ad6265SDimitry Andric // is used. This is needed to calculate the size of the function. 82881ad6265SDimitry Andric MCSymbol *FnEndSym = createTempSymbol("func_end"); 82981ad6265SDimitry Andric OutStreamer->emitLabel(FnEndSym); 83081ad6265SDimitry Andric 83181ad6265SDimitry Andric OutStreamer->pushSection(); 83281ad6265SDimitry Andric OutStreamer->switchSection(getObjFileLowering().getPPA1Section()); 83381ad6265SDimitry Andric emitPPA1(FnEndSym); 83481ad6265SDimitry Andric OutStreamer->popSection(); 83581ad6265SDimitry Andric 83681ad6265SDimitry Andric CurrentFnPPA1Sym = nullptr; 83781ad6265SDimitry Andric CurrentFnEPMarkerSym = nullptr; 83881ad6265SDimitry Andric } 83981ad6265SDimitry Andric } 84081ad6265SDimitry Andric 84181ad6265SDimitry Andric static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg, 84281ad6265SDimitry Andric bool StackProtector, bool FPRMask, bool VRMask) { 84381ad6265SDimitry Andric enum class PPA1Flag1 : uint8_t { 84481ad6265SDimitry Andric DSA64Bit = (0x80 >> 0), 84581ad6265SDimitry Andric VarArg = (0x80 >> 7), 84681ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(DSA64Bit) 84781ad6265SDimitry Andric }; 84881ad6265SDimitry Andric enum class PPA1Flag2 : uint8_t { 84981ad6265SDimitry Andric ExternalProcedure = (0x80 >> 0), 85081ad6265SDimitry Andric STACKPROTECTOR = (0x80 >> 3), 85181ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure) 85281ad6265SDimitry Andric }; 85381ad6265SDimitry Andric enum class PPA1Flag3 : uint8_t { 85481ad6265SDimitry Andric FPRMask = (0x80 >> 2), 85581ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(FPRMask) 85681ad6265SDimitry Andric }; 85781ad6265SDimitry Andric enum class PPA1Flag4 : uint8_t { 85881ad6265SDimitry Andric EPMOffsetPresent = (0x80 >> 0), 85981ad6265SDimitry Andric VRMask = (0x80 >> 2), 86081ad6265SDimitry Andric ProcedureNamePresent = (0x80 >> 7), 86181ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent) 86281ad6265SDimitry Andric }; 86381ad6265SDimitry Andric 86481ad6265SDimitry Andric // Declare optional section flags that can be modified. 86581ad6265SDimitry Andric auto Flags1 = PPA1Flag1(0); 86681ad6265SDimitry Andric auto Flags2 = PPA1Flag2::ExternalProcedure; 86781ad6265SDimitry Andric auto Flags3 = PPA1Flag3(0); 86881ad6265SDimitry Andric auto Flags4 = PPA1Flag4::EPMOffsetPresent | PPA1Flag4::ProcedureNamePresent; 86981ad6265SDimitry Andric 87081ad6265SDimitry Andric Flags1 |= PPA1Flag1::DSA64Bit; 87181ad6265SDimitry Andric 87281ad6265SDimitry Andric if (VarArg) 87381ad6265SDimitry Andric Flags1 |= PPA1Flag1::VarArg; 87481ad6265SDimitry Andric 87581ad6265SDimitry Andric if (StackProtector) 87681ad6265SDimitry Andric Flags2 |= PPA1Flag2::STACKPROTECTOR; 87781ad6265SDimitry Andric 87881ad6265SDimitry Andric // SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in. 87981ad6265SDimitry Andric if (FPRMask) 88081ad6265SDimitry Andric Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag. 88181ad6265SDimitry Andric 88281ad6265SDimitry Andric if (VRMask) 88381ad6265SDimitry Andric Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag. 88481ad6265SDimitry Andric 88581ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 1"); 88681ad6265SDimitry Andric if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit) 88781ad6265SDimitry Andric OutStreamer->AddComment(" Bit 0: 1 = 64-bit DSA"); 88881ad6265SDimitry Andric else 88981ad6265SDimitry Andric OutStreamer->AddComment(" Bit 0: 0 = 32-bit DSA"); 89081ad6265SDimitry Andric if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg) 89181ad6265SDimitry Andric OutStreamer->AddComment(" Bit 7: 1 = Vararg function"); 89281ad6265SDimitry Andric OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1. 89381ad6265SDimitry Andric 89481ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 2"); 89581ad6265SDimitry Andric if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure) 89681ad6265SDimitry Andric OutStreamer->AddComment(" Bit 0: 1 = External procedure"); 89781ad6265SDimitry Andric if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR) 89881ad6265SDimitry Andric OutStreamer->AddComment(" Bit 3: 1 = STACKPROTECT is enabled"); 89981ad6265SDimitry Andric else 90081ad6265SDimitry Andric OutStreamer->AddComment(" Bit 3: 0 = STACKPROTECT is not enabled"); 90181ad6265SDimitry Andric OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2. 90281ad6265SDimitry Andric 90381ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 3"); 90481ad6265SDimitry Andric if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask) 90581ad6265SDimitry Andric OutStreamer->AddComment(" Bit 2: 1 = FP Reg Mask is in optional area"); 90681ad6265SDimitry Andric OutStreamer->emitInt8( 90781ad6265SDimitry Andric static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections). 90881ad6265SDimitry Andric 90981ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 4"); 91081ad6265SDimitry Andric if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask) 91181ad6265SDimitry Andric OutStreamer->AddComment(" Bit 2: 1 = Vector Reg Mask is in optional area"); 91281ad6265SDimitry Andric OutStreamer->emitInt8(static_cast<uint8_t>( 91381ad6265SDimitry Andric Flags4)); // Flags 4 (optional sections, always emit these). 91481ad6265SDimitry Andric } 91581ad6265SDimitry Andric 91681ad6265SDimitry Andric void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) { 91781ad6265SDimitry Andric const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo(); 91881ad6265SDimitry Andric const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 91981ad6265SDimitry Andric const auto TargetHasVector = Subtarget.hasVector(); 92081ad6265SDimitry Andric 92181ad6265SDimitry Andric const SystemZMachineFunctionInfo *ZFI = 92281ad6265SDimitry Andric MF->getInfo<SystemZMachineFunctionInfo>(); 92381ad6265SDimitry Andric const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>( 92481ad6265SDimitry Andric Subtarget.getFrameLowering()); 92581ad6265SDimitry Andric const MachineFrameInfo &MFFrame = MF->getFrameInfo(); 92681ad6265SDimitry Andric 92781ad6265SDimitry Andric // Get saved GPR/FPR/VPR masks. 92881ad6265SDimitry Andric const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo(); 92981ad6265SDimitry Andric uint16_t SavedGPRMask = 0; 93081ad6265SDimitry Andric uint16_t SavedFPRMask = 0; 93181ad6265SDimitry Andric uint8_t SavedVRMask = 0; 93281ad6265SDimitry Andric int64_t OffsetFPR = 0; 93381ad6265SDimitry Andric int64_t OffsetVR = 0; 93481ad6265SDimitry Andric const int64_t TopOfStack = 93581ad6265SDimitry Andric MFFrame.getOffsetAdjustment() + MFFrame.getStackSize(); 93681ad6265SDimitry Andric 93781ad6265SDimitry Andric // Loop over the spilled registers. The CalleeSavedInfo can't be used because 93881ad6265SDimitry Andric // it does not contain all spilled registers. 93981ad6265SDimitry Andric for (unsigned I = ZFI->getSpillGPRRegs().LowGPR, 94081ad6265SDimitry Andric E = ZFI->getSpillGPRRegs().HighGPR; 94181ad6265SDimitry Andric I && E && I <= E; ++I) { 94281ad6265SDimitry Andric unsigned V = TRI->getEncodingValue((Register)I); 94381ad6265SDimitry Andric assert(V < 16 && "GPR index out of range"); 94481ad6265SDimitry Andric SavedGPRMask |= 1 << (15 - V); 94581ad6265SDimitry Andric } 94681ad6265SDimitry Andric 94781ad6265SDimitry Andric for (auto &CS : CSI) { 94881ad6265SDimitry Andric unsigned Reg = CS.getReg(); 94981ad6265SDimitry Andric unsigned I = TRI->getEncodingValue(Reg); 95081ad6265SDimitry Andric 95181ad6265SDimitry Andric if (SystemZ::FP64BitRegClass.contains(Reg)) { 95281ad6265SDimitry Andric assert(I < 16 && "FPR index out of range"); 95381ad6265SDimitry Andric SavedFPRMask |= 1 << (15 - I); 95481ad6265SDimitry Andric int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx()); 95581ad6265SDimitry Andric if (Temp < OffsetFPR) 95681ad6265SDimitry Andric OffsetFPR = Temp; 95781ad6265SDimitry Andric } else if (SystemZ::VR128BitRegClass.contains(Reg)) { 95881ad6265SDimitry Andric assert(I >= 16 && I <= 23 && "VPR index out of range"); 95981ad6265SDimitry Andric unsigned BitNum = I - 16; 96081ad6265SDimitry Andric SavedVRMask |= 1 << (7 - BitNum); 96181ad6265SDimitry Andric int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx()); 96281ad6265SDimitry Andric if (Temp < OffsetVR) 96381ad6265SDimitry Andric OffsetVR = Temp; 96481ad6265SDimitry Andric } 96581ad6265SDimitry Andric } 96681ad6265SDimitry Andric 96781ad6265SDimitry Andric // Adjust the offset. 96881ad6265SDimitry Andric OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0; 96981ad6265SDimitry Andric OffsetVR += (OffsetVR < 0) ? TopOfStack : 0; 97081ad6265SDimitry Andric 97181ad6265SDimitry Andric // Get alloca register. 97281ad6265SDimitry Andric uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF)); 97381ad6265SDimitry Andric uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0; 97481ad6265SDimitry Andric assert(AllocaReg < 16 && "Can't have alloca register larger than 15"); 97581ad6265SDimitry Andric (void)AllocaReg; 97681ad6265SDimitry Andric 97781ad6265SDimitry Andric // Build FPR save area offset. 97881ad6265SDimitry Andric uint32_t FrameAndFPROffset = 0; 97981ad6265SDimitry Andric if (SavedFPRMask) { 98081ad6265SDimitry Andric uint64_t FPRSaveAreaOffset = OffsetFPR; 98181ad6265SDimitry Andric assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range"); 98281ad6265SDimitry Andric 98381ad6265SDimitry Andric FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits. 98481ad6265SDimitry Andric FrameAndFPROffset |= FrameReg << 28; // Put into top 4 bits. 98581ad6265SDimitry Andric } 98681ad6265SDimitry Andric 98781ad6265SDimitry Andric // Build VR save area offset. 98881ad6265SDimitry Andric uint32_t FrameAndVROffset = 0; 98981ad6265SDimitry Andric if (TargetHasVector && SavedVRMask) { 99081ad6265SDimitry Andric uint64_t VRSaveAreaOffset = OffsetVR; 99181ad6265SDimitry Andric assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range"); 99281ad6265SDimitry Andric 99381ad6265SDimitry Andric FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits. 99481ad6265SDimitry Andric FrameAndVROffset |= FrameReg << 28; // Put into top 4 bits. 99581ad6265SDimitry Andric } 99681ad6265SDimitry Andric 99781ad6265SDimitry Andric // Emit PPA1 section. 99881ad6265SDimitry Andric OutStreamer->AddComment("PPA1"); 99981ad6265SDimitry Andric OutStreamer->emitLabel(CurrentFnPPA1Sym); 100081ad6265SDimitry Andric OutStreamer->AddComment("Version"); 100181ad6265SDimitry Andric OutStreamer->emitInt8(0x02); // Version. 100281ad6265SDimitry Andric OutStreamer->AddComment("LE Signature X'CE'"); 100381ad6265SDimitry Andric OutStreamer->emitInt8(0xCE); // CEL signature. 100481ad6265SDimitry Andric OutStreamer->AddComment("Saved GPR Mask"); 100581ad6265SDimitry Andric OutStreamer->emitInt16(SavedGPRMask); 100681ad6265SDimitry Andric 100781ad6265SDimitry Andric emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(), 100881ad6265SDimitry Andric MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0, 100981ad6265SDimitry Andric TargetHasVector && SavedVRMask != 0); 101081ad6265SDimitry Andric 101181ad6265SDimitry Andric OutStreamer->AddComment("Length/4 of Parms"); 101281ad6265SDimitry Andric OutStreamer->emitInt16( 101381ad6265SDimitry Andric static_cast<uint16_t>(MFFrame.getMaxCallFrameSize() / 4)); // Parms/4. 101481ad6265SDimitry Andric OutStreamer->AddComment("Length of Code"); 101581ad6265SDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4); 101681ad6265SDimitry Andric 101781ad6265SDimitry Andric // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3). 101881ad6265SDimitry Andric if (SavedFPRMask) { 101981ad6265SDimitry Andric OutStreamer->AddComment("FPR mask"); 102081ad6265SDimitry Andric OutStreamer->emitInt16(SavedFPRMask); 102181ad6265SDimitry Andric OutStreamer->AddComment("AR mask"); 102281ad6265SDimitry Andric OutStreamer->emitInt16(0); // AR Mask, unused currently. 102381ad6265SDimitry Andric OutStreamer->AddComment("FPR Save Area Locator"); 102481ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 0-3: Register R") 102581ad6265SDimitry Andric .concat(utostr(FrameAndFPROffset >> 28)) 102681ad6265SDimitry Andric .str()); 102781ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 4-31: Offset ") 102881ad6265SDimitry Andric .concat(utostr(FrameAndFPROffset & 0x0FFFFFFF)) 102981ad6265SDimitry Andric .str()); 103081ad6265SDimitry Andric OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with 103181ad6265SDimitry Andric // register to add value to 103281ad6265SDimitry Andric // (alloca reg). 103381ad6265SDimitry Andric } 103481ad6265SDimitry Andric 103581ad6265SDimitry Andric // Emit saved VR mask to VR save area. 103681ad6265SDimitry Andric if (TargetHasVector && SavedVRMask) { 103781ad6265SDimitry Andric OutStreamer->AddComment("VR mask"); 103881ad6265SDimitry Andric OutStreamer->emitInt8(SavedVRMask); 103981ad6265SDimitry Andric OutStreamer->emitInt8(0); // Reserved. 104081ad6265SDimitry Andric OutStreamer->emitInt16(0); // Also reserved. 104181ad6265SDimitry Andric OutStreamer->AddComment("VR Save Area Locator"); 104281ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 0-3: Register R") 104381ad6265SDimitry Andric .concat(utostr(FrameAndVROffset >> 28)) 104481ad6265SDimitry Andric .str()); 104581ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 4-31: Offset ") 104681ad6265SDimitry Andric .concat(utostr(FrameAndVROffset & 0x0FFFFFFF)) 104781ad6265SDimitry Andric .str()); 104881ad6265SDimitry Andric OutStreamer->emitInt32(FrameAndVROffset); 104981ad6265SDimitry Andric } 105081ad6265SDimitry Andric 105181ad6265SDimitry Andric // Emit offset to entry point optional section (0x80 of flags 4). 105281ad6265SDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym, 105381ad6265SDimitry Andric 4); 105481ad6265SDimitry Andric } 105581ad6265SDimitry Andric 105604eeddc0SDimitry Andric void SystemZAsmPrinter::emitFunctionEntryLabel() { 105781ad6265SDimitry Andric const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 105804eeddc0SDimitry Andric 105904eeddc0SDimitry Andric if (Subtarget.getTargetTriple().isOSzOS()) { 106004eeddc0SDimitry Andric MCContext &OutContext = OutStreamer->getContext(); 106181ad6265SDimitry Andric 106281ad6265SDimitry Andric // Save information for later use. 106381ad6265SDimitry Andric std::string N(MF->getFunction().hasName() 106481ad6265SDimitry Andric ? Twine(MF->getFunction().getName()).concat("_").str() 106581ad6265SDimitry Andric : ""); 106681ad6265SDimitry Andric 106781ad6265SDimitry Andric CurrentFnEPMarkerSym = 106881ad6265SDimitry Andric OutContext.createTempSymbol(Twine("EPM_").concat(N).str(), true); 106981ad6265SDimitry Andric CurrentFnPPA1Sym = 107081ad6265SDimitry Andric OutContext.createTempSymbol(Twine("PPA1_").concat(N).str(), true); 107104eeddc0SDimitry Andric 107204eeddc0SDimitry Andric // EntryPoint Marker 107304eeddc0SDimitry Andric const MachineFrameInfo &MFFrame = MF->getFrameInfo(); 107404eeddc0SDimitry Andric bool IsUsingAlloca = MFFrame.hasVarSizedObjects(); 107504eeddc0SDimitry Andric 107604eeddc0SDimitry Andric // Set Flags 107704eeddc0SDimitry Andric uint8_t Flags = 0; 107804eeddc0SDimitry Andric if (IsUsingAlloca) 107904eeddc0SDimitry Andric Flags |= 0x04; 108004eeddc0SDimitry Andric 108104eeddc0SDimitry Andric uint32_t DSASize = MFFrame.getStackSize(); 108204eeddc0SDimitry Andric 108304eeddc0SDimitry Andric // Combine into top 27 bits of DSASize and bottom 5 bits of Flags. 108404eeddc0SDimitry Andric uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5 108504eeddc0SDimitry Andric DSAAndFlags |= Flags; 108604eeddc0SDimitry Andric 108704eeddc0SDimitry Andric // Emit entry point marker section. 108804eeddc0SDimitry Andric OutStreamer->AddComment("XPLINK Routine Layout Entry"); 108981ad6265SDimitry Andric OutStreamer->emitLabel(CurrentFnEPMarkerSym); 109004eeddc0SDimitry Andric OutStreamer->AddComment("Eyecatcher 0x00C300C500C500"); 109104eeddc0SDimitry Andric OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher. 109204eeddc0SDimitry Andric OutStreamer->AddComment("Mark Type C'1'"); 109304eeddc0SDimitry Andric OutStreamer->emitInt8(0xF1); // Mark Type. 109481ad6265SDimitry Andric OutStreamer->AddComment("Offset to PPA1"); 109581ad6265SDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(CurrentFnPPA1Sym, CurrentFnEPMarkerSym, 109681ad6265SDimitry Andric 4); 109704eeddc0SDimitry Andric if (OutStreamer->isVerboseAsm()) { 109804eeddc0SDimitry Andric OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize)); 109904eeddc0SDimitry Andric OutStreamer->AddComment("Entry Flags"); 110004eeddc0SDimitry Andric if (Flags & 0x04) 110104eeddc0SDimitry Andric OutStreamer->AddComment(" Bit 2: 1 = Uses alloca"); 110204eeddc0SDimitry Andric else 110304eeddc0SDimitry Andric OutStreamer->AddComment(" Bit 2: 0 = Does not use alloca"); 110404eeddc0SDimitry Andric } 110504eeddc0SDimitry Andric OutStreamer->emitInt32(DSAAndFlags); 110604eeddc0SDimitry Andric } 110704eeddc0SDimitry Andric 110804eeddc0SDimitry Andric AsmPrinter::emitFunctionEntryLabel(); 110904eeddc0SDimitry Andric } 111004eeddc0SDimitry Andric 11110b57cec5SDimitry Andric // Force static initialization. 1112480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() { 11130b57cec5SDimitry Andric RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget()); 11140b57cec5SDimitry Andric } 1115