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) { 91*81ad6265SDimitry Andric if (MI->memoperands_empty()) 920b57cec5SDimitry Andric return; 93*81ad6265SDimitry Andric 94*81ad6265SDimitry Andric Align Alignment = Align(16); 95*81ad6265SDimitry Andric for (MachineInstr::mmo_iterator MMOI = MI->memoperands_begin(), 96*81ad6265SDimitry Andric EE = MI->memoperands_end(); MMOI != EE; ++MMOI) 97*81ad6265SDimitry Andric if ((*MMOI)->getAlign() < Alignment) 98*81ad6265SDimitry Andric Alignment = (*MMOI)->getAlign(); 99*81ad6265SDimitry Andric 1000b57cec5SDimitry Andric unsigned AlignmentHint = 0; 101*81ad6265SDimitry Andric if (Alignment >= Align(16)) 1020b57cec5SDimitry Andric AlignmentHint = 4; 103*81ad6265SDimitry 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 133*81ad6265SDimitry Andric // The XPLINK ABI requires that a no-op encoding the call type is emitted after 134*81ad6265SDimitry Andric // each call to a subroutine. This information can be used by the called 135*81ad6265SDimitry Andric // function to determine its entry point, e.g. for generating a backtrace. The 136*81ad6265SDimitry Andric // call type is encoded as a register number in the bcr instruction. See 137*81ad6265SDimitry Andric // enumeration CallType for the possible values. 138*81ad6265SDimitry Andric void SystemZAsmPrinter::emitCallInformation(CallType CT) { 139*81ad6265SDimitry Andric EmitToStreamer(*OutStreamer, 140*81ad6265SDimitry Andric MCInstBuilder(SystemZ::BCRAsm) 141*81ad6265SDimitry Andric .addImm(0) 142*81ad6265SDimitry Andric .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)])); 143*81ad6265SDimitry Andric } 144*81ad6265SDimitry Andric 1455ffd83dbSDimitry Andric void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) { 1460b57cec5SDimitry Andric SystemZMCInstLower Lower(MF->getContext(), *this); 1470b57cec5SDimitry Andric MCInst LoweredMI; 1480b57cec5SDimitry Andric switch (MI->getOpcode()) { 1490b57cec5SDimitry Andric case SystemZ::Return: 150*81ad6265SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BR) 151*81ad6265SDimitry Andric .addReg(SystemZ::R14D); 152*81ad6265SDimitry Andric break; 153*81ad6265SDimitry Andric 154*81ad6265SDimitry Andric case SystemZ::Return_XPLINK: 155*81ad6265SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::B) 156*81ad6265SDimitry Andric .addReg(SystemZ::R7D) 157*81ad6265SDimitry Andric .addImm(2) 158*81ad6265SDimitry Andric .addReg(0); 1590b57cec5SDimitry Andric break; 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric case SystemZ::CondReturn: 1620b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BCR) 1630b57cec5SDimitry Andric .addImm(MI->getOperand(0).getImm()) 1640b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 1650b57cec5SDimitry Andric .addReg(SystemZ::R14D); 1660b57cec5SDimitry Andric break; 1670b57cec5SDimitry Andric 168*81ad6265SDimitry Andric case SystemZ::CondReturn_XPLINK: 169*81ad6265SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BC) 170*81ad6265SDimitry Andric .addImm(MI->getOperand(0).getImm()) 171*81ad6265SDimitry Andric .addImm(MI->getOperand(1).getImm()) 172*81ad6265SDimitry Andric .addReg(SystemZ::R7D) 173*81ad6265SDimitry Andric .addImm(2) 174*81ad6265SDimitry Andric .addReg(0); 175*81ad6265SDimitry Andric break; 176*81ad6265SDimitry Andric 1770b57cec5SDimitry Andric case SystemZ::CRBReturn: 1780b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CRB) 1790b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 1800b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 1810b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 1820b57cec5SDimitry Andric .addReg(SystemZ::R14D) 1830b57cec5SDimitry Andric .addImm(0); 1840b57cec5SDimitry Andric break; 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric case SystemZ::CGRBReturn: 1870b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CGRB) 1880b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 1890b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 1900b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 1910b57cec5SDimitry Andric .addReg(SystemZ::R14D) 1920b57cec5SDimitry Andric .addImm(0); 1930b57cec5SDimitry Andric break; 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric case SystemZ::CIBReturn: 1960b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CIB) 1970b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 1980b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 1990b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2000b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2010b57cec5SDimitry Andric .addImm(0); 2020b57cec5SDimitry Andric break; 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric case SystemZ::CGIBReturn: 2050b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CGIB) 2060b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2070b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2080b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2090b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2100b57cec5SDimitry Andric .addImm(0); 2110b57cec5SDimitry Andric break; 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric case SystemZ::CLRBReturn: 2140b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLRB) 2150b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2160b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 2170b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2180b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2190b57cec5SDimitry Andric .addImm(0); 2200b57cec5SDimitry Andric break; 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric case SystemZ::CLGRBReturn: 2230b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLGRB) 2240b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2250b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 2260b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2270b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2280b57cec5SDimitry Andric .addImm(0); 2290b57cec5SDimitry Andric break; 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric case SystemZ::CLIBReturn: 2320b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLIB) 2330b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2340b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2350b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2360b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2370b57cec5SDimitry Andric .addImm(0); 2380b57cec5SDimitry Andric break; 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric case SystemZ::CLGIBReturn: 2410b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLGIB) 2420b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2430b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2440b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2450b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2460b57cec5SDimitry Andric .addImm(0); 2470b57cec5SDimitry Andric break; 2480b57cec5SDimitry Andric 249fe6060f1SDimitry Andric case SystemZ::CallBRASL_XPLINK64: 250fe6060f1SDimitry Andric EmitToStreamer(*OutStreamer, 251fe6060f1SDimitry Andric MCInstBuilder(SystemZ::BRASL) 252fe6060f1SDimitry Andric .addReg(SystemZ::R7D) 253fe6060f1SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), 254fe6060f1SDimitry Andric MCSymbolRefExpr::VK_PLT))); 255*81ad6265SDimitry Andric emitCallInformation(CallType::BRASL7); 256fe6060f1SDimitry Andric return; 257fe6060f1SDimitry Andric 258fe6060f1SDimitry Andric case SystemZ::CallBASR_XPLINK64: 259fe6060f1SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 260fe6060f1SDimitry Andric .addReg(SystemZ::R7D) 261fe6060f1SDimitry Andric .addReg(MI->getOperand(0).getReg())); 262*81ad6265SDimitry Andric emitCallInformation(CallType::BASR76); 263*81ad6265SDimitry Andric return; 264*81ad6265SDimitry Andric 265*81ad6265SDimitry Andric case SystemZ::CallBASR_STACKEXT: 266*81ad6265SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 267*81ad6265SDimitry Andric .addReg(SystemZ::R3D) 268*81ad6265SDimitry Andric .addReg(MI->getOperand(0).getReg())); 269*81ad6265SDimitry Andric emitCallInformation(CallType::BASR33); 270fe6060f1SDimitry Andric return; 271fe6060f1SDimitry Andric 2720b57cec5SDimitry Andric case SystemZ::CallBRASL: 2730b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRASL) 2740b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2750b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 2760b57cec5SDimitry Andric break; 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric case SystemZ::CallBASR: 2790b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BASR) 2800b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2810b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()); 2820b57cec5SDimitry Andric break; 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric case SystemZ::CallJG: 2850b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::JG) 2860b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 2870b57cec5SDimitry Andric break; 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric case SystemZ::CallBRCL: 2900b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRCL) 2910b57cec5SDimitry Andric .addImm(MI->getOperand(0).getImm()) 2920b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2930b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT)); 2940b57cec5SDimitry Andric break; 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric case SystemZ::CallBR: 297e8d8bef9SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BR) 298e8d8bef9SDimitry Andric .addReg(MI->getOperand(0).getReg()); 2990b57cec5SDimitry Andric break; 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric case SystemZ::CallBCR: 3020b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BCR) 3030b57cec5SDimitry Andric .addImm(MI->getOperand(0).getImm()) 3040b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 305e8d8bef9SDimitry Andric .addReg(MI->getOperand(2).getReg()); 3060b57cec5SDimitry Andric break; 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric case SystemZ::CRBCall: 3090b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CRB) 3100b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3110b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 3120b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 313e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 3140b57cec5SDimitry Andric .addImm(0); 3150b57cec5SDimitry Andric break; 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric case SystemZ::CGRBCall: 3180b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CGRB) 3190b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3200b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 3210b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 322e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 3230b57cec5SDimitry Andric .addImm(0); 3240b57cec5SDimitry Andric break; 3250b57cec5SDimitry Andric 3260b57cec5SDimitry Andric case SystemZ::CIBCall: 3270b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CIB) 3280b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3290b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 3300b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 331e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 3320b57cec5SDimitry Andric .addImm(0); 3330b57cec5SDimitry Andric break; 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric case SystemZ::CGIBCall: 3360b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CGIB) 3370b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3380b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 3390b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 340e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 3410b57cec5SDimitry Andric .addImm(0); 3420b57cec5SDimitry Andric break; 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric case SystemZ::CLRBCall: 3450b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLRB) 3460b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3470b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 3480b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 349e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 3500b57cec5SDimitry Andric .addImm(0); 3510b57cec5SDimitry Andric break; 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric case SystemZ::CLGRBCall: 3540b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLGRB) 3550b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3560b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 3570b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 358e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 3590b57cec5SDimitry Andric .addImm(0); 3600b57cec5SDimitry Andric break; 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric case SystemZ::CLIBCall: 3630b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLIB) 3640b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3650b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 3660b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 367e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 3680b57cec5SDimitry Andric .addImm(0); 3690b57cec5SDimitry Andric break; 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric case SystemZ::CLGIBCall: 3720b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLGIB) 3730b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3740b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 3750b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 376e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 3770b57cec5SDimitry Andric .addImm(0); 3780b57cec5SDimitry Andric break; 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric case SystemZ::TLS_GDCALL: 3810b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRASL) 3820b57cec5SDimitry Andric .addReg(SystemZ::R14D) 3830b57cec5SDimitry Andric .addExpr(getTLSGetOffset(MF->getContext())) 3840b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD)); 3850b57cec5SDimitry Andric break; 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric case SystemZ::TLS_LDCALL: 3880b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRASL) 3890b57cec5SDimitry Andric .addReg(SystemZ::R14D) 3900b57cec5SDimitry Andric .addExpr(getTLSGetOffset(MF->getContext())) 3910b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM)); 3920b57cec5SDimitry Andric break; 3930b57cec5SDimitry Andric 3940b57cec5SDimitry Andric case SystemZ::GOT: 3950b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::LARL) 3960b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3970b57cec5SDimitry Andric .addExpr(getGlobalOffsetTable(MF->getContext())); 3980b57cec5SDimitry Andric break; 3990b57cec5SDimitry Andric 4000b57cec5SDimitry Andric case SystemZ::IILF64: 4010b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::IILF) 4020b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 4030b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()); 4040b57cec5SDimitry Andric break; 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric case SystemZ::IIHF64: 4070b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::IIHF) 4080b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 4090b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()); 4100b57cec5SDimitry Andric break; 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric case SystemZ::RISBHH: 4130b57cec5SDimitry Andric case SystemZ::RISBHL: 4140b57cec5SDimitry Andric LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG); 4150b57cec5SDimitry Andric break; 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric case SystemZ::RISBLH: 4180b57cec5SDimitry Andric case SystemZ::RISBLL: 4190b57cec5SDimitry Andric LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG); 4200b57cec5SDimitry Andric break; 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric case SystemZ::VLVGP32: 4230b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::VLVGP) 4240b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4250b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg())) 4260b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())); 4270b57cec5SDimitry Andric break; 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric case SystemZ::VLR32: 4300b57cec5SDimitry Andric case SystemZ::VLR64: 4310b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::VLR) 4320b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 4330b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())); 4340b57cec5SDimitry Andric break; 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric case SystemZ::VL: 4370b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 4380b57cec5SDimitry Andric lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign); 4390b57cec5SDimitry Andric break; 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric case SystemZ::VST: 4420b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 4430b57cec5SDimitry Andric lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign); 4440b57cec5SDimitry Andric break; 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric case SystemZ::VLM: 4470b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 4480b57cec5SDimitry Andric lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign); 4490b57cec5SDimitry Andric break; 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric case SystemZ::VSTM: 4520b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 4530b57cec5SDimitry Andric lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign); 4540b57cec5SDimitry Andric break; 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric case SystemZ::VL32: 4570b57cec5SDimitry Andric LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF); 4580b57cec5SDimitry Andric break; 4590b57cec5SDimitry Andric 4600b57cec5SDimitry Andric case SystemZ::VL64: 4610b57cec5SDimitry Andric LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG); 4620b57cec5SDimitry Andric break; 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric case SystemZ::VST32: 4650b57cec5SDimitry Andric LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF); 4660b57cec5SDimitry Andric break; 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric case SystemZ::VST64: 4690b57cec5SDimitry Andric LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG); 4700b57cec5SDimitry Andric break; 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric case SystemZ::LFER: 4730b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::VLGVF) 4740b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg())) 4750b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())) 4760b57cec5SDimitry Andric .addReg(0).addImm(0); 4770b57cec5SDimitry Andric break; 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric case SystemZ::LEFR: 4800b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::VLVGF) 4810b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 4820b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 4830b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 4840b57cec5SDimitry Andric .addReg(0).addImm(0); 4850b57cec5SDimitry Andric break; 4860b57cec5SDimitry Andric 4870b57cec5SDimitry Andric #define LOWER_LOW(NAME) \ 4880b57cec5SDimitry Andric case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric LOWER_LOW(IILL); 4910b57cec5SDimitry Andric LOWER_LOW(IILH); 4920b57cec5SDimitry Andric LOWER_LOW(TMLL); 4930b57cec5SDimitry Andric LOWER_LOW(TMLH); 4940b57cec5SDimitry Andric LOWER_LOW(NILL); 4950b57cec5SDimitry Andric LOWER_LOW(NILH); 4960b57cec5SDimitry Andric LOWER_LOW(NILF); 4970b57cec5SDimitry Andric LOWER_LOW(OILL); 4980b57cec5SDimitry Andric LOWER_LOW(OILH); 4990b57cec5SDimitry Andric LOWER_LOW(OILF); 5000b57cec5SDimitry Andric LOWER_LOW(XILF); 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric #undef LOWER_LOW 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric #define LOWER_HIGH(NAME) \ 5050b57cec5SDimitry Andric case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric LOWER_HIGH(IIHL); 5080b57cec5SDimitry Andric LOWER_HIGH(IIHH); 5090b57cec5SDimitry Andric LOWER_HIGH(TMHL); 5100b57cec5SDimitry Andric LOWER_HIGH(TMHH); 5110b57cec5SDimitry Andric LOWER_HIGH(NIHL); 5120b57cec5SDimitry Andric LOWER_HIGH(NIHH); 5130b57cec5SDimitry Andric LOWER_HIGH(NIHF); 5140b57cec5SDimitry Andric LOWER_HIGH(OIHL); 5150b57cec5SDimitry Andric LOWER_HIGH(OIHH); 5160b57cec5SDimitry Andric LOWER_HIGH(OIHF); 5170b57cec5SDimitry Andric LOWER_HIGH(XIHF); 5180b57cec5SDimitry Andric 5190b57cec5SDimitry Andric #undef LOWER_HIGH 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric case SystemZ::Serialize: 5220b57cec5SDimitry Andric if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization()) 5230b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BCRAsm) 5240b57cec5SDimitry Andric .addImm(14).addReg(SystemZ::R0D); 5250b57cec5SDimitry Andric else 5260b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BCRAsm) 5270b57cec5SDimitry Andric .addImm(15).addReg(SystemZ::R0D); 5280b57cec5SDimitry Andric break; 5290b57cec5SDimitry Andric 5300b57cec5SDimitry Andric // Emit nothing here but a comment if we can. 5310b57cec5SDimitry Andric case SystemZ::MemBarrier: 5320b57cec5SDimitry Andric OutStreamer->emitRawComment("MEMBARRIER"); 5330b57cec5SDimitry Andric return; 5340b57cec5SDimitry Andric 5350b57cec5SDimitry Andric // We want to emit "j .+2" for traps, jumping to the relative immediate field 5360b57cec5SDimitry Andric // of the jump instruction, which is an illegal instruction. We cannot emit a 5370b57cec5SDimitry Andric // "." symbol, so create and emit a temp label before the instruction and use 5380b57cec5SDimitry Andric // that instead. 5390b57cec5SDimitry Andric case SystemZ::Trap: { 5400b57cec5SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 5415ffd83dbSDimitry Andric OutStreamer->emitLabel(DotSym); 5420b57cec5SDimitry Andric 5430b57cec5SDimitry Andric const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 5440b57cec5SDimitry Andric const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 5450b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::J) 5460b57cec5SDimitry Andric .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric break; 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric // Conditional traps will create a branch on condition instruction that jumps 5510b57cec5SDimitry Andric // to the relative immediate field of the jump instruction. (eg. "jo .+2") 5520b57cec5SDimitry Andric case SystemZ::CondTrap: { 5530b57cec5SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 5545ffd83dbSDimitry Andric OutStreamer->emitLabel(DotSym); 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 5570b57cec5SDimitry Andric const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 5580b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRC) 5590b57cec5SDimitry Andric .addImm(MI->getOperand(0).getImm()) 5600b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 5610b57cec5SDimitry Andric .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric break; 5640b57cec5SDimitry Andric 5658bcb0991SDimitry Andric case TargetOpcode::FENTRY_CALL: 5668bcb0991SDimitry Andric LowerFENTRY_CALL(*MI, Lower); 5678bcb0991SDimitry Andric return; 5688bcb0991SDimitry Andric 5690b57cec5SDimitry Andric case TargetOpcode::STACKMAP: 5700b57cec5SDimitry Andric LowerSTACKMAP(*MI); 5710b57cec5SDimitry Andric return; 5720b57cec5SDimitry Andric 5730b57cec5SDimitry Andric case TargetOpcode::PATCHPOINT: 5740b57cec5SDimitry Andric LowerPATCHPOINT(*MI, Lower); 5750b57cec5SDimitry Andric return; 5760b57cec5SDimitry Andric 577fe6060f1SDimitry Andric case SystemZ::EXRL_Pseudo: { 578fe6060f1SDimitry Andric unsigned TargetInsOpc = MI->getOperand(0).getImm(); 579fe6060f1SDimitry Andric Register LenMinus1Reg = MI->getOperand(1).getReg(); 580fe6060f1SDimitry Andric Register DestReg = MI->getOperand(2).getReg(); 581fe6060f1SDimitry Andric int64_t DestDisp = MI->getOperand(3).getImm(); 582fe6060f1SDimitry Andric Register SrcReg = MI->getOperand(4).getReg(); 583fe6060f1SDimitry Andric int64_t SrcDisp = MI->getOperand(5).getImm(); 584fe6060f1SDimitry Andric 585349cc55cSDimitry Andric SystemZTargetStreamer *TS = getTargetStreamer(); 586fe6060f1SDimitry Andric MCSymbol *DotSym = nullptr; 587fe6060f1SDimitry Andric MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg) 588fe6060f1SDimitry Andric .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp); 589349cc55cSDimitry Andric SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget()); 590349cc55cSDimitry Andric SystemZTargetStreamer::EXRLT2SymMap::iterator I = 591349cc55cSDimitry Andric TS->EXRLTargets2Sym.find(ET_STI); 592349cc55cSDimitry Andric if (I != TS->EXRLTargets2Sym.end()) 593fe6060f1SDimitry Andric DotSym = I->second; 594fe6060f1SDimitry Andric else 595349cc55cSDimitry Andric TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol(); 596fe6060f1SDimitry Andric const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); 597fe6060f1SDimitry Andric EmitToStreamer( 598fe6060f1SDimitry Andric *OutStreamer, 599fe6060f1SDimitry Andric MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot)); 600fe6060f1SDimitry Andric return; 601fe6060f1SDimitry Andric } 602fe6060f1SDimitry Andric 6030b57cec5SDimitry Andric default: 6040b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 6050b57cec5SDimitry Andric break; 6060b57cec5SDimitry Andric } 6070b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, LoweredMI); 6080b57cec5SDimitry Andric } 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric // Emit the largest nop instruction smaller than or equal to NumBytes 6110b57cec5SDimitry Andric // bytes. Return the size of nop emitted. 6120b57cec5SDimitry Andric static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer, 6130b57cec5SDimitry Andric unsigned NumBytes, const MCSubtargetInfo &STI) { 6140b57cec5SDimitry Andric if (NumBytes < 2) { 6150b57cec5SDimitry Andric llvm_unreachable("Zero nops?"); 6160b57cec5SDimitry Andric return 0; 6170b57cec5SDimitry Andric } 6180b57cec5SDimitry Andric else if (NumBytes < 4) { 6195ffd83dbSDimitry Andric OutStreamer.emitInstruction( 6205ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI); 6210b57cec5SDimitry Andric return 2; 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric else if (NumBytes < 6) { 6245ffd83dbSDimitry Andric OutStreamer.emitInstruction( 6255ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0), 6260b57cec5SDimitry Andric STI); 6270b57cec5SDimitry Andric return 4; 6280b57cec5SDimitry Andric } 6290b57cec5SDimitry Andric else { 6300b57cec5SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 6310b57cec5SDimitry Andric const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); 6325ffd83dbSDimitry Andric OutStreamer.emitLabel(DotSym); 6335ffd83dbSDimitry Andric OutStreamer.emitInstruction( 6345ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI); 6350b57cec5SDimitry Andric return 6; 6360b57cec5SDimitry Andric } 6370b57cec5SDimitry Andric } 6380b57cec5SDimitry Andric 6398bcb0991SDimitry Andric void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI, 6408bcb0991SDimitry Andric SystemZMCInstLower &Lower) { 6418bcb0991SDimitry Andric MCContext &Ctx = MF->getContext(); 642480093f4SDimitry Andric if (MF->getFunction().hasFnAttribute("mrecord-mcount")) { 643480093f4SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 644*81ad6265SDimitry Andric OutStreamer->pushSection(); 645*81ad6265SDimitry Andric OutStreamer->switchSection( 646480093f4SDimitry Andric Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC)); 6475ffd83dbSDimitry Andric OutStreamer->emitSymbolValue(DotSym, 8); 648*81ad6265SDimitry Andric OutStreamer->popSection(); 6495ffd83dbSDimitry Andric OutStreamer->emitLabel(DotSym); 650480093f4SDimitry Andric } 651480093f4SDimitry Andric 652480093f4SDimitry Andric if (MF->getFunction().hasFnAttribute("mnop-mcount")) { 6538bcb0991SDimitry Andric EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo()); 6548bcb0991SDimitry Andric return; 6558bcb0991SDimitry Andric } 6568bcb0991SDimitry Andric 6578bcb0991SDimitry Andric MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__"); 6588bcb0991SDimitry Andric const MCSymbolRefExpr *Op = 6598bcb0991SDimitry Andric MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx); 6605ffd83dbSDimitry Andric OutStreamer->emitInstruction( 6615ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op), 6625ffd83dbSDimitry Andric getSubtargetInfo()); 6638bcb0991SDimitry Andric } 6648bcb0991SDimitry Andric 6650b57cec5SDimitry Andric void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) { 666*81ad6265SDimitry Andric auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo(); 6670b57cec5SDimitry Andric 6680b57cec5SDimitry Andric unsigned NumNOPBytes = MI.getOperand(1).getImm(); 6690b57cec5SDimitry Andric 670480093f4SDimitry Andric auto &Ctx = OutStreamer->getContext(); 671480093f4SDimitry Andric MCSymbol *MILabel = Ctx.createTempSymbol(); 6725ffd83dbSDimitry Andric OutStreamer->emitLabel(MILabel); 673480093f4SDimitry Andric 674480093f4SDimitry Andric SM.recordStackMap(*MILabel, MI); 6750b57cec5SDimitry Andric assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!"); 6760b57cec5SDimitry Andric 6770b57cec5SDimitry Andric // Scan ahead to trim the shadow. 6780b57cec5SDimitry Andric unsigned ShadowBytes = 0; 6790b57cec5SDimitry Andric const MachineBasicBlock &MBB = *MI.getParent(); 6800b57cec5SDimitry Andric MachineBasicBlock::const_iterator MII(MI); 6810b57cec5SDimitry Andric ++MII; 6820b57cec5SDimitry Andric while (ShadowBytes < NumNOPBytes) { 6830b57cec5SDimitry Andric if (MII == MBB.end() || 6840b57cec5SDimitry Andric MII->getOpcode() == TargetOpcode::PATCHPOINT || 6850b57cec5SDimitry Andric MII->getOpcode() == TargetOpcode::STACKMAP) 6860b57cec5SDimitry Andric break; 6870b57cec5SDimitry Andric ShadowBytes += TII->getInstSizeInBytes(*MII); 6880b57cec5SDimitry Andric if (MII->isCall()) 6890b57cec5SDimitry Andric break; 6900b57cec5SDimitry Andric ++MII; 6910b57cec5SDimitry Andric } 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric // Emit nops. 6940b57cec5SDimitry Andric while (ShadowBytes < NumNOPBytes) 6950b57cec5SDimitry Andric ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes, 6960b57cec5SDimitry Andric getSubtargetInfo()); 6970b57cec5SDimitry Andric } 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric // Lower a patchpoint of the form: 7000b57cec5SDimitry Andric // [<def>], <id>, <numBytes>, <target>, <numArgs> 7010b57cec5SDimitry Andric void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI, 7020b57cec5SDimitry Andric SystemZMCInstLower &Lower) { 703480093f4SDimitry Andric auto &Ctx = OutStreamer->getContext(); 704480093f4SDimitry Andric MCSymbol *MILabel = Ctx.createTempSymbol(); 7055ffd83dbSDimitry Andric OutStreamer->emitLabel(MILabel); 706480093f4SDimitry Andric 707480093f4SDimitry Andric SM.recordPatchPoint(*MILabel, MI); 7080b57cec5SDimitry Andric PatchPointOpers Opers(&MI); 7090b57cec5SDimitry Andric 7100b57cec5SDimitry Andric unsigned EncodedBytes = 0; 7110b57cec5SDimitry Andric const MachineOperand &CalleeMO = Opers.getCallTarget(); 7120b57cec5SDimitry Andric 7130b57cec5SDimitry Andric if (CalleeMO.isImm()) { 7140b57cec5SDimitry Andric uint64_t CallTarget = CalleeMO.getImm(); 7150b57cec5SDimitry Andric if (CallTarget) { 7160b57cec5SDimitry Andric unsigned ScratchIdx = -1; 7170b57cec5SDimitry Andric unsigned ScratchReg = 0; 7180b57cec5SDimitry Andric do { 7190b57cec5SDimitry Andric ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1); 7200b57cec5SDimitry Andric ScratchReg = MI.getOperand(ScratchIdx).getReg(); 7210b57cec5SDimitry Andric } while (ScratchReg == SystemZ::R0D); 7220b57cec5SDimitry Andric 7230b57cec5SDimitry Andric // Materialize the call target address 7240b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF) 7250b57cec5SDimitry Andric .addReg(ScratchReg) 7260b57cec5SDimitry Andric .addImm(CallTarget & 0xFFFFFFFF)); 7270b57cec5SDimitry Andric EncodedBytes += 6; 7280b57cec5SDimitry Andric if (CallTarget >> 32) { 7290b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF) 7300b57cec5SDimitry Andric .addReg(ScratchReg) 7310b57cec5SDimitry Andric .addImm(CallTarget >> 32)); 7320b57cec5SDimitry Andric EncodedBytes += 6; 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 7360b57cec5SDimitry Andric .addReg(SystemZ::R14D) 7370b57cec5SDimitry Andric .addReg(ScratchReg)); 7380b57cec5SDimitry Andric EncodedBytes += 2; 7390b57cec5SDimitry Andric } 7400b57cec5SDimitry Andric } else if (CalleeMO.isGlobal()) { 7410b57cec5SDimitry Andric const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT); 7420b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL) 7430b57cec5SDimitry Andric .addReg(SystemZ::R14D) 7440b57cec5SDimitry Andric .addExpr(Expr)); 7450b57cec5SDimitry Andric EncodedBytes += 6; 7460b57cec5SDimitry Andric } 7470b57cec5SDimitry Andric 7480b57cec5SDimitry Andric // Emit padding. 7490b57cec5SDimitry Andric unsigned NumBytes = Opers.getNumPatchBytes(); 7500b57cec5SDimitry Andric assert(NumBytes >= EncodedBytes && 7510b57cec5SDimitry Andric "Patchpoint can't request size less than the length of a call."); 7520b57cec5SDimitry Andric assert((NumBytes - EncodedBytes) % 2 == 0 && 7530b57cec5SDimitry Andric "Invalid number of NOP bytes requested!"); 7540b57cec5SDimitry Andric while (EncodedBytes < NumBytes) 7550b57cec5SDimitry Andric EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes, 7560b57cec5SDimitry Andric getSubtargetInfo()); 7570b57cec5SDimitry Andric } 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric // Convert a SystemZ-specific constant pool modifier into the associated 7600b57cec5SDimitry Andric // MCSymbolRefExpr variant kind. 7610b57cec5SDimitry Andric static MCSymbolRefExpr::VariantKind 7620b57cec5SDimitry Andric getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) { 7630b57cec5SDimitry Andric switch (Modifier) { 7640b57cec5SDimitry Andric case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD; 7650b57cec5SDimitry Andric case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM; 7660b57cec5SDimitry Andric case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF; 7670b57cec5SDimitry Andric case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF; 7680b57cec5SDimitry Andric } 7690b57cec5SDimitry Andric llvm_unreachable("Invalid SystemCPModifier!"); 7700b57cec5SDimitry Andric } 7710b57cec5SDimitry Andric 7725ffd83dbSDimitry Andric void SystemZAsmPrinter::emitMachineConstantPoolValue( 7735ffd83dbSDimitry Andric MachineConstantPoolValue *MCPV) { 7740b57cec5SDimitry Andric auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV); 7750b57cec5SDimitry Andric 7760b57cec5SDimitry Andric const MCExpr *Expr = 7770b57cec5SDimitry Andric MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()), 7780b57cec5SDimitry Andric getModifierVariantKind(ZCPV->getModifier()), 7790b57cec5SDimitry Andric OutContext); 7800b57cec5SDimitry Andric uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType()); 7810b57cec5SDimitry Andric 7825ffd83dbSDimitry Andric OutStreamer->emitValue(Expr, Size); 7830b57cec5SDimitry Andric } 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 7860b57cec5SDimitry Andric const char *ExtraCode, 7870b57cec5SDimitry Andric raw_ostream &OS) { 788fe6060f1SDimitry Andric const MCRegisterInfo &MRI = *TM.getMCRegisterInfo(); 789fe6060f1SDimitry Andric const MachineOperand &MO = MI->getOperand(OpNo); 790fe6060f1SDimitry Andric MCOperand MCOp; 791fe6060f1SDimitry Andric if (ExtraCode) { 792fe6060f1SDimitry Andric if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() && 793fe6060f1SDimitry Andric SystemZ::GR128BitRegClass.contains(MO.getReg())) 794fe6060f1SDimitry Andric MCOp = 795fe6060f1SDimitry Andric MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64)); 796fe6060f1SDimitry Andric else 7970b57cec5SDimitry Andric return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS); 798fe6060f1SDimitry Andric } else { 7990b57cec5SDimitry Andric SystemZMCInstLower Lower(MF->getContext(), *this); 800fe6060f1SDimitry Andric MCOp = Lower.lowerOperand(MO); 801fe6060f1SDimitry Andric } 802fe6060f1SDimitry Andric SystemZInstPrinter::printOperand(MCOp, MAI, OS); 8030b57cec5SDimitry Andric return false; 8040b57cec5SDimitry Andric } 8050b57cec5SDimitry Andric 8060b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 8070b57cec5SDimitry Andric unsigned OpNo, 8080b57cec5SDimitry Andric const char *ExtraCode, 8090b57cec5SDimitry Andric raw_ostream &OS) { 810349cc55cSDimitry Andric SystemZInstPrinter:: 811349cc55cSDimitry Andric printAddress(MAI, MI->getOperand(OpNo).getReg(), 812349cc55cSDimitry Andric MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()), 8130b57cec5SDimitry Andric MI->getOperand(OpNo + 2).getReg(), OS); 8140b57cec5SDimitry Andric return false; 8150b57cec5SDimitry Andric } 8160b57cec5SDimitry Andric 8175ffd83dbSDimitry Andric void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) { 8180b57cec5SDimitry Andric emitStackMaps(SM); 8190b57cec5SDimitry Andric } 8200b57cec5SDimitry Andric 821*81ad6265SDimitry Andric void SystemZAsmPrinter::emitFunctionBodyEnd() { 822*81ad6265SDimitry Andric if (TM.getTargetTriple().isOSzOS()) { 823*81ad6265SDimitry Andric // Emit symbol for the end of function if the z/OS target streamer 824*81ad6265SDimitry Andric // is used. This is needed to calculate the size of the function. 825*81ad6265SDimitry Andric MCSymbol *FnEndSym = createTempSymbol("func_end"); 826*81ad6265SDimitry Andric OutStreamer->emitLabel(FnEndSym); 827*81ad6265SDimitry Andric 828*81ad6265SDimitry Andric OutStreamer->pushSection(); 829*81ad6265SDimitry Andric OutStreamer->switchSection(getObjFileLowering().getPPA1Section()); 830*81ad6265SDimitry Andric emitPPA1(FnEndSym); 831*81ad6265SDimitry Andric OutStreamer->popSection(); 832*81ad6265SDimitry Andric 833*81ad6265SDimitry Andric CurrentFnPPA1Sym = nullptr; 834*81ad6265SDimitry Andric CurrentFnEPMarkerSym = nullptr; 835*81ad6265SDimitry Andric } 836*81ad6265SDimitry Andric } 837*81ad6265SDimitry Andric 838*81ad6265SDimitry Andric static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg, 839*81ad6265SDimitry Andric bool StackProtector, bool FPRMask, bool VRMask) { 840*81ad6265SDimitry Andric enum class PPA1Flag1 : uint8_t { 841*81ad6265SDimitry Andric DSA64Bit = (0x80 >> 0), 842*81ad6265SDimitry Andric VarArg = (0x80 >> 7), 843*81ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(DSA64Bit) 844*81ad6265SDimitry Andric }; 845*81ad6265SDimitry Andric enum class PPA1Flag2 : uint8_t { 846*81ad6265SDimitry Andric ExternalProcedure = (0x80 >> 0), 847*81ad6265SDimitry Andric STACKPROTECTOR = (0x80 >> 3), 848*81ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure) 849*81ad6265SDimitry Andric }; 850*81ad6265SDimitry Andric enum class PPA1Flag3 : uint8_t { 851*81ad6265SDimitry Andric FPRMask = (0x80 >> 2), 852*81ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(FPRMask) 853*81ad6265SDimitry Andric }; 854*81ad6265SDimitry Andric enum class PPA1Flag4 : uint8_t { 855*81ad6265SDimitry Andric EPMOffsetPresent = (0x80 >> 0), 856*81ad6265SDimitry Andric VRMask = (0x80 >> 2), 857*81ad6265SDimitry Andric ProcedureNamePresent = (0x80 >> 7), 858*81ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent) 859*81ad6265SDimitry Andric }; 860*81ad6265SDimitry Andric 861*81ad6265SDimitry Andric // Declare optional section flags that can be modified. 862*81ad6265SDimitry Andric auto Flags1 = PPA1Flag1(0); 863*81ad6265SDimitry Andric auto Flags2 = PPA1Flag2::ExternalProcedure; 864*81ad6265SDimitry Andric auto Flags3 = PPA1Flag3(0); 865*81ad6265SDimitry Andric auto Flags4 = PPA1Flag4::EPMOffsetPresent | PPA1Flag4::ProcedureNamePresent; 866*81ad6265SDimitry Andric 867*81ad6265SDimitry Andric Flags1 |= PPA1Flag1::DSA64Bit; 868*81ad6265SDimitry Andric 869*81ad6265SDimitry Andric if (VarArg) 870*81ad6265SDimitry Andric Flags1 |= PPA1Flag1::VarArg; 871*81ad6265SDimitry Andric 872*81ad6265SDimitry Andric if (StackProtector) 873*81ad6265SDimitry Andric Flags2 |= PPA1Flag2::STACKPROTECTOR; 874*81ad6265SDimitry Andric 875*81ad6265SDimitry Andric // SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in. 876*81ad6265SDimitry Andric if (FPRMask) 877*81ad6265SDimitry Andric Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag. 878*81ad6265SDimitry Andric 879*81ad6265SDimitry Andric if (VRMask) 880*81ad6265SDimitry Andric Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag. 881*81ad6265SDimitry Andric 882*81ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 1"); 883*81ad6265SDimitry Andric if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit) 884*81ad6265SDimitry Andric OutStreamer->AddComment(" Bit 0: 1 = 64-bit DSA"); 885*81ad6265SDimitry Andric else 886*81ad6265SDimitry Andric OutStreamer->AddComment(" Bit 0: 0 = 32-bit DSA"); 887*81ad6265SDimitry Andric if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg) 888*81ad6265SDimitry Andric OutStreamer->AddComment(" Bit 7: 1 = Vararg function"); 889*81ad6265SDimitry Andric OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1. 890*81ad6265SDimitry Andric 891*81ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 2"); 892*81ad6265SDimitry Andric if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure) 893*81ad6265SDimitry Andric OutStreamer->AddComment(" Bit 0: 1 = External procedure"); 894*81ad6265SDimitry Andric if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR) 895*81ad6265SDimitry Andric OutStreamer->AddComment(" Bit 3: 1 = STACKPROTECT is enabled"); 896*81ad6265SDimitry Andric else 897*81ad6265SDimitry Andric OutStreamer->AddComment(" Bit 3: 0 = STACKPROTECT is not enabled"); 898*81ad6265SDimitry Andric OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2. 899*81ad6265SDimitry Andric 900*81ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 3"); 901*81ad6265SDimitry Andric if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask) 902*81ad6265SDimitry Andric OutStreamer->AddComment(" Bit 2: 1 = FP Reg Mask is in optional area"); 903*81ad6265SDimitry Andric OutStreamer->emitInt8( 904*81ad6265SDimitry Andric static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections). 905*81ad6265SDimitry Andric 906*81ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 4"); 907*81ad6265SDimitry Andric if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask) 908*81ad6265SDimitry Andric OutStreamer->AddComment(" Bit 2: 1 = Vector Reg Mask is in optional area"); 909*81ad6265SDimitry Andric OutStreamer->emitInt8(static_cast<uint8_t>( 910*81ad6265SDimitry Andric Flags4)); // Flags 4 (optional sections, always emit these). 911*81ad6265SDimitry Andric } 912*81ad6265SDimitry Andric 913*81ad6265SDimitry Andric void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) { 914*81ad6265SDimitry Andric const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo(); 915*81ad6265SDimitry Andric const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 916*81ad6265SDimitry Andric const auto TargetHasVector = Subtarget.hasVector(); 917*81ad6265SDimitry Andric 918*81ad6265SDimitry Andric const SystemZMachineFunctionInfo *ZFI = 919*81ad6265SDimitry Andric MF->getInfo<SystemZMachineFunctionInfo>(); 920*81ad6265SDimitry Andric const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>( 921*81ad6265SDimitry Andric Subtarget.getFrameLowering()); 922*81ad6265SDimitry Andric const MachineFrameInfo &MFFrame = MF->getFrameInfo(); 923*81ad6265SDimitry Andric 924*81ad6265SDimitry Andric // Get saved GPR/FPR/VPR masks. 925*81ad6265SDimitry Andric const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo(); 926*81ad6265SDimitry Andric uint16_t SavedGPRMask = 0; 927*81ad6265SDimitry Andric uint16_t SavedFPRMask = 0; 928*81ad6265SDimitry Andric uint8_t SavedVRMask = 0; 929*81ad6265SDimitry Andric int64_t OffsetFPR = 0; 930*81ad6265SDimitry Andric int64_t OffsetVR = 0; 931*81ad6265SDimitry Andric const int64_t TopOfStack = 932*81ad6265SDimitry Andric MFFrame.getOffsetAdjustment() + MFFrame.getStackSize(); 933*81ad6265SDimitry Andric 934*81ad6265SDimitry Andric // Loop over the spilled registers. The CalleeSavedInfo can't be used because 935*81ad6265SDimitry Andric // it does not contain all spilled registers. 936*81ad6265SDimitry Andric for (unsigned I = ZFI->getSpillGPRRegs().LowGPR, 937*81ad6265SDimitry Andric E = ZFI->getSpillGPRRegs().HighGPR; 938*81ad6265SDimitry Andric I && E && I <= E; ++I) { 939*81ad6265SDimitry Andric unsigned V = TRI->getEncodingValue((Register)I); 940*81ad6265SDimitry Andric assert(V < 16 && "GPR index out of range"); 941*81ad6265SDimitry Andric SavedGPRMask |= 1 << (15 - V); 942*81ad6265SDimitry Andric } 943*81ad6265SDimitry Andric 944*81ad6265SDimitry Andric for (auto &CS : CSI) { 945*81ad6265SDimitry Andric unsigned Reg = CS.getReg(); 946*81ad6265SDimitry Andric unsigned I = TRI->getEncodingValue(Reg); 947*81ad6265SDimitry Andric 948*81ad6265SDimitry Andric if (SystemZ::FP64BitRegClass.contains(Reg)) { 949*81ad6265SDimitry Andric assert(I < 16 && "FPR index out of range"); 950*81ad6265SDimitry Andric SavedFPRMask |= 1 << (15 - I); 951*81ad6265SDimitry Andric int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx()); 952*81ad6265SDimitry Andric if (Temp < OffsetFPR) 953*81ad6265SDimitry Andric OffsetFPR = Temp; 954*81ad6265SDimitry Andric } else if (SystemZ::VR128BitRegClass.contains(Reg)) { 955*81ad6265SDimitry Andric assert(I >= 16 && I <= 23 && "VPR index out of range"); 956*81ad6265SDimitry Andric unsigned BitNum = I - 16; 957*81ad6265SDimitry Andric SavedVRMask |= 1 << (7 - BitNum); 958*81ad6265SDimitry Andric int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx()); 959*81ad6265SDimitry Andric if (Temp < OffsetVR) 960*81ad6265SDimitry Andric OffsetVR = Temp; 961*81ad6265SDimitry Andric } 962*81ad6265SDimitry Andric } 963*81ad6265SDimitry Andric 964*81ad6265SDimitry Andric // Adjust the offset. 965*81ad6265SDimitry Andric OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0; 966*81ad6265SDimitry Andric OffsetVR += (OffsetVR < 0) ? TopOfStack : 0; 967*81ad6265SDimitry Andric 968*81ad6265SDimitry Andric // Get alloca register. 969*81ad6265SDimitry Andric uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF)); 970*81ad6265SDimitry Andric uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0; 971*81ad6265SDimitry Andric assert(AllocaReg < 16 && "Can't have alloca register larger than 15"); 972*81ad6265SDimitry Andric (void)AllocaReg; 973*81ad6265SDimitry Andric 974*81ad6265SDimitry Andric // Build FPR save area offset. 975*81ad6265SDimitry Andric uint32_t FrameAndFPROffset = 0; 976*81ad6265SDimitry Andric if (SavedFPRMask) { 977*81ad6265SDimitry Andric uint64_t FPRSaveAreaOffset = OffsetFPR; 978*81ad6265SDimitry Andric assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range"); 979*81ad6265SDimitry Andric 980*81ad6265SDimitry Andric FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits. 981*81ad6265SDimitry Andric FrameAndFPROffset |= FrameReg << 28; // Put into top 4 bits. 982*81ad6265SDimitry Andric } 983*81ad6265SDimitry Andric 984*81ad6265SDimitry Andric // Build VR save area offset. 985*81ad6265SDimitry Andric uint32_t FrameAndVROffset = 0; 986*81ad6265SDimitry Andric if (TargetHasVector && SavedVRMask) { 987*81ad6265SDimitry Andric uint64_t VRSaveAreaOffset = OffsetVR; 988*81ad6265SDimitry Andric assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range"); 989*81ad6265SDimitry Andric 990*81ad6265SDimitry Andric FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits. 991*81ad6265SDimitry Andric FrameAndVROffset |= FrameReg << 28; // Put into top 4 bits. 992*81ad6265SDimitry Andric } 993*81ad6265SDimitry Andric 994*81ad6265SDimitry Andric // Emit PPA1 section. 995*81ad6265SDimitry Andric OutStreamer->AddComment("PPA1"); 996*81ad6265SDimitry Andric OutStreamer->emitLabel(CurrentFnPPA1Sym); 997*81ad6265SDimitry Andric OutStreamer->AddComment("Version"); 998*81ad6265SDimitry Andric OutStreamer->emitInt8(0x02); // Version. 999*81ad6265SDimitry Andric OutStreamer->AddComment("LE Signature X'CE'"); 1000*81ad6265SDimitry Andric OutStreamer->emitInt8(0xCE); // CEL signature. 1001*81ad6265SDimitry Andric OutStreamer->AddComment("Saved GPR Mask"); 1002*81ad6265SDimitry Andric OutStreamer->emitInt16(SavedGPRMask); 1003*81ad6265SDimitry Andric 1004*81ad6265SDimitry Andric emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(), 1005*81ad6265SDimitry Andric MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0, 1006*81ad6265SDimitry Andric TargetHasVector && SavedVRMask != 0); 1007*81ad6265SDimitry Andric 1008*81ad6265SDimitry Andric OutStreamer->AddComment("Length/4 of Parms"); 1009*81ad6265SDimitry Andric OutStreamer->emitInt16( 1010*81ad6265SDimitry Andric static_cast<uint16_t>(MFFrame.getMaxCallFrameSize() / 4)); // Parms/4. 1011*81ad6265SDimitry Andric OutStreamer->AddComment("Length of Code"); 1012*81ad6265SDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4); 1013*81ad6265SDimitry Andric 1014*81ad6265SDimitry Andric // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3). 1015*81ad6265SDimitry Andric if (SavedFPRMask) { 1016*81ad6265SDimitry Andric OutStreamer->AddComment("FPR mask"); 1017*81ad6265SDimitry Andric OutStreamer->emitInt16(SavedFPRMask); 1018*81ad6265SDimitry Andric OutStreamer->AddComment("AR mask"); 1019*81ad6265SDimitry Andric OutStreamer->emitInt16(0); // AR Mask, unused currently. 1020*81ad6265SDimitry Andric OutStreamer->AddComment("FPR Save Area Locator"); 1021*81ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 0-3: Register R") 1022*81ad6265SDimitry Andric .concat(utostr(FrameAndFPROffset >> 28)) 1023*81ad6265SDimitry Andric .str()); 1024*81ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 4-31: Offset ") 1025*81ad6265SDimitry Andric .concat(utostr(FrameAndFPROffset & 0x0FFFFFFF)) 1026*81ad6265SDimitry Andric .str()); 1027*81ad6265SDimitry Andric OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with 1028*81ad6265SDimitry Andric // register to add value to 1029*81ad6265SDimitry Andric // (alloca reg). 1030*81ad6265SDimitry Andric } 1031*81ad6265SDimitry Andric 1032*81ad6265SDimitry Andric // Emit saved VR mask to VR save area. 1033*81ad6265SDimitry Andric if (TargetHasVector && SavedVRMask) { 1034*81ad6265SDimitry Andric OutStreamer->AddComment("VR mask"); 1035*81ad6265SDimitry Andric OutStreamer->emitInt8(SavedVRMask); 1036*81ad6265SDimitry Andric OutStreamer->emitInt8(0); // Reserved. 1037*81ad6265SDimitry Andric OutStreamer->emitInt16(0); // Also reserved. 1038*81ad6265SDimitry Andric OutStreamer->AddComment("VR Save Area Locator"); 1039*81ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 0-3: Register R") 1040*81ad6265SDimitry Andric .concat(utostr(FrameAndVROffset >> 28)) 1041*81ad6265SDimitry Andric .str()); 1042*81ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 4-31: Offset ") 1043*81ad6265SDimitry Andric .concat(utostr(FrameAndVROffset & 0x0FFFFFFF)) 1044*81ad6265SDimitry Andric .str()); 1045*81ad6265SDimitry Andric OutStreamer->emitInt32(FrameAndVROffset); 1046*81ad6265SDimitry Andric } 1047*81ad6265SDimitry Andric 1048*81ad6265SDimitry Andric // Emit offset to entry point optional section (0x80 of flags 4). 1049*81ad6265SDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym, 1050*81ad6265SDimitry Andric 4); 1051*81ad6265SDimitry Andric } 1052*81ad6265SDimitry Andric 105304eeddc0SDimitry Andric void SystemZAsmPrinter::emitFunctionEntryLabel() { 1054*81ad6265SDimitry Andric const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 105504eeddc0SDimitry Andric 105604eeddc0SDimitry Andric if (Subtarget.getTargetTriple().isOSzOS()) { 105704eeddc0SDimitry Andric MCContext &OutContext = OutStreamer->getContext(); 1058*81ad6265SDimitry Andric 1059*81ad6265SDimitry Andric // Save information for later use. 1060*81ad6265SDimitry Andric std::string N(MF->getFunction().hasName() 1061*81ad6265SDimitry Andric ? Twine(MF->getFunction().getName()).concat("_").str() 1062*81ad6265SDimitry Andric : ""); 1063*81ad6265SDimitry Andric 1064*81ad6265SDimitry Andric CurrentFnEPMarkerSym = 1065*81ad6265SDimitry Andric OutContext.createTempSymbol(Twine("EPM_").concat(N).str(), true); 1066*81ad6265SDimitry Andric CurrentFnPPA1Sym = 1067*81ad6265SDimitry Andric OutContext.createTempSymbol(Twine("PPA1_").concat(N).str(), true); 106804eeddc0SDimitry Andric 106904eeddc0SDimitry Andric // EntryPoint Marker 107004eeddc0SDimitry Andric const MachineFrameInfo &MFFrame = MF->getFrameInfo(); 107104eeddc0SDimitry Andric bool IsUsingAlloca = MFFrame.hasVarSizedObjects(); 107204eeddc0SDimitry Andric 107304eeddc0SDimitry Andric // Set Flags 107404eeddc0SDimitry Andric uint8_t Flags = 0; 107504eeddc0SDimitry Andric if (IsUsingAlloca) 107604eeddc0SDimitry Andric Flags |= 0x04; 107704eeddc0SDimitry Andric 107804eeddc0SDimitry Andric uint32_t DSASize = MFFrame.getStackSize(); 107904eeddc0SDimitry Andric 108004eeddc0SDimitry Andric // Combine into top 27 bits of DSASize and bottom 5 bits of Flags. 108104eeddc0SDimitry Andric uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5 108204eeddc0SDimitry Andric DSAAndFlags |= Flags; 108304eeddc0SDimitry Andric 108404eeddc0SDimitry Andric // Emit entry point marker section. 108504eeddc0SDimitry Andric OutStreamer->AddComment("XPLINK Routine Layout Entry"); 1086*81ad6265SDimitry Andric OutStreamer->emitLabel(CurrentFnEPMarkerSym); 108704eeddc0SDimitry Andric OutStreamer->AddComment("Eyecatcher 0x00C300C500C500"); 108804eeddc0SDimitry Andric OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher. 108904eeddc0SDimitry Andric OutStreamer->AddComment("Mark Type C'1'"); 109004eeddc0SDimitry Andric OutStreamer->emitInt8(0xF1); // Mark Type. 1091*81ad6265SDimitry Andric OutStreamer->AddComment("Offset to PPA1"); 1092*81ad6265SDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(CurrentFnPPA1Sym, CurrentFnEPMarkerSym, 1093*81ad6265SDimitry Andric 4); 109404eeddc0SDimitry Andric if (OutStreamer->isVerboseAsm()) { 109504eeddc0SDimitry Andric OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize)); 109604eeddc0SDimitry Andric OutStreamer->AddComment("Entry Flags"); 109704eeddc0SDimitry Andric if (Flags & 0x04) 109804eeddc0SDimitry Andric OutStreamer->AddComment(" Bit 2: 1 = Uses alloca"); 109904eeddc0SDimitry Andric else 110004eeddc0SDimitry Andric OutStreamer->AddComment(" Bit 2: 0 = Does not use alloca"); 110104eeddc0SDimitry Andric } 110204eeddc0SDimitry Andric OutStreamer->emitInt32(DSAAndFlags); 110304eeddc0SDimitry Andric } 110404eeddc0SDimitry Andric 110504eeddc0SDimitry Andric AsmPrinter::emitFunctionEntryLabel(); 110604eeddc0SDimitry Andric } 110704eeddc0SDimitry Andric 11080b57cec5SDimitry Andric // Force static initialization. 1109480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() { 11100b57cec5SDimitry Andric RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget()); 11110b57cec5SDimitry Andric } 1112