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) { 146753f127fSDimitry Andric SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(), 147753f127fSDimitry Andric getSubtargetInfo().getFeatureBits()); 148753f127fSDimitry 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 // We want to emit "j .+2" for traps, jumping to the relative immediate field 5340b57cec5SDimitry Andric // of the jump instruction, which is an illegal instruction. We cannot emit a 5350b57cec5SDimitry Andric // "." symbol, so create and emit a temp label before the instruction and use 5360b57cec5SDimitry Andric // that instead. 5370b57cec5SDimitry Andric case SystemZ::Trap: { 5380b57cec5SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 5395ffd83dbSDimitry Andric OutStreamer->emitLabel(DotSym); 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 5420b57cec5SDimitry Andric const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 5430b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::J) 5440b57cec5SDimitry Andric .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric break; 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric // Conditional traps will create a branch on condition instruction that jumps 5490b57cec5SDimitry Andric // to the relative immediate field of the jump instruction. (eg. "jo .+2") 5500b57cec5SDimitry Andric case SystemZ::CondTrap: { 5510b57cec5SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 5525ffd83dbSDimitry Andric OutStreamer->emitLabel(DotSym); 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 5550b57cec5SDimitry Andric const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 5560b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRC) 5570b57cec5SDimitry Andric .addImm(MI->getOperand(0).getImm()) 5580b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 5590b57cec5SDimitry Andric .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric break; 5620b57cec5SDimitry Andric 5638bcb0991SDimitry Andric case TargetOpcode::FENTRY_CALL: 5648bcb0991SDimitry Andric LowerFENTRY_CALL(*MI, Lower); 5658bcb0991SDimitry Andric return; 5668bcb0991SDimitry Andric 5670b57cec5SDimitry Andric case TargetOpcode::STACKMAP: 5680b57cec5SDimitry Andric LowerSTACKMAP(*MI); 5690b57cec5SDimitry Andric return; 5700b57cec5SDimitry Andric 5710b57cec5SDimitry Andric case TargetOpcode::PATCHPOINT: 5720b57cec5SDimitry Andric LowerPATCHPOINT(*MI, Lower); 5730b57cec5SDimitry Andric return; 5740b57cec5SDimitry Andric 575fe6060f1SDimitry Andric case SystemZ::EXRL_Pseudo: { 576fe6060f1SDimitry Andric unsigned TargetInsOpc = MI->getOperand(0).getImm(); 577fe6060f1SDimitry Andric Register LenMinus1Reg = MI->getOperand(1).getReg(); 578fe6060f1SDimitry Andric Register DestReg = MI->getOperand(2).getReg(); 579fe6060f1SDimitry Andric int64_t DestDisp = MI->getOperand(3).getImm(); 580fe6060f1SDimitry Andric Register SrcReg = MI->getOperand(4).getReg(); 581fe6060f1SDimitry Andric int64_t SrcDisp = MI->getOperand(5).getImm(); 582fe6060f1SDimitry Andric 583349cc55cSDimitry Andric SystemZTargetStreamer *TS = getTargetStreamer(); 584fe6060f1SDimitry Andric MCSymbol *DotSym = nullptr; 585fe6060f1SDimitry Andric MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg) 586fe6060f1SDimitry Andric .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp); 587349cc55cSDimitry Andric SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget()); 588349cc55cSDimitry Andric SystemZTargetStreamer::EXRLT2SymMap::iterator I = 589349cc55cSDimitry Andric TS->EXRLTargets2Sym.find(ET_STI); 590349cc55cSDimitry Andric if (I != TS->EXRLTargets2Sym.end()) 591fe6060f1SDimitry Andric DotSym = I->second; 592fe6060f1SDimitry Andric else 593349cc55cSDimitry Andric TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol(); 594fe6060f1SDimitry Andric const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); 595fe6060f1SDimitry Andric EmitToStreamer( 596fe6060f1SDimitry Andric *OutStreamer, 597fe6060f1SDimitry Andric MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot)); 598fe6060f1SDimitry Andric return; 599fe6060f1SDimitry Andric } 600fe6060f1SDimitry Andric 6010b57cec5SDimitry Andric default: 6020b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 6030b57cec5SDimitry Andric break; 6040b57cec5SDimitry Andric } 6050b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, LoweredMI); 6060b57cec5SDimitry Andric } 6070b57cec5SDimitry Andric 6080b57cec5SDimitry Andric // Emit the largest nop instruction smaller than or equal to NumBytes 6090b57cec5SDimitry Andric // bytes. Return the size of nop emitted. 6100b57cec5SDimitry Andric static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer, 6110b57cec5SDimitry Andric unsigned NumBytes, const MCSubtargetInfo &STI) { 6120b57cec5SDimitry Andric if (NumBytes < 2) { 6130b57cec5SDimitry Andric llvm_unreachable("Zero nops?"); 6140b57cec5SDimitry Andric return 0; 6150b57cec5SDimitry Andric } 6160b57cec5SDimitry Andric else if (NumBytes < 4) { 6175ffd83dbSDimitry Andric OutStreamer.emitInstruction( 6185ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI); 6190b57cec5SDimitry Andric return 2; 6200b57cec5SDimitry Andric } 6210b57cec5SDimitry Andric else if (NumBytes < 6) { 6225ffd83dbSDimitry Andric OutStreamer.emitInstruction( 6235ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0), 6240b57cec5SDimitry Andric STI); 6250b57cec5SDimitry Andric return 4; 6260b57cec5SDimitry Andric } 6270b57cec5SDimitry Andric else { 6280b57cec5SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 6290b57cec5SDimitry Andric const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); 6305ffd83dbSDimitry Andric OutStreamer.emitLabel(DotSym); 6315ffd83dbSDimitry Andric OutStreamer.emitInstruction( 6325ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI); 6330b57cec5SDimitry Andric return 6; 6340b57cec5SDimitry Andric } 6350b57cec5SDimitry Andric } 6360b57cec5SDimitry Andric 6378bcb0991SDimitry Andric void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI, 6388bcb0991SDimitry Andric SystemZMCInstLower &Lower) { 6398bcb0991SDimitry Andric MCContext &Ctx = MF->getContext(); 640480093f4SDimitry Andric if (MF->getFunction().hasFnAttribute("mrecord-mcount")) { 641480093f4SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 64281ad6265SDimitry Andric OutStreamer->pushSection(); 64381ad6265SDimitry Andric OutStreamer->switchSection( 644480093f4SDimitry Andric Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC)); 6455ffd83dbSDimitry Andric OutStreamer->emitSymbolValue(DotSym, 8); 64681ad6265SDimitry Andric OutStreamer->popSection(); 6475ffd83dbSDimitry Andric OutStreamer->emitLabel(DotSym); 648480093f4SDimitry Andric } 649480093f4SDimitry Andric 650480093f4SDimitry Andric if (MF->getFunction().hasFnAttribute("mnop-mcount")) { 6518bcb0991SDimitry Andric EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo()); 6528bcb0991SDimitry Andric return; 6538bcb0991SDimitry Andric } 6548bcb0991SDimitry Andric 6558bcb0991SDimitry Andric MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__"); 6568bcb0991SDimitry Andric const MCSymbolRefExpr *Op = 6578bcb0991SDimitry Andric MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx); 6585ffd83dbSDimitry Andric OutStreamer->emitInstruction( 6595ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op), 6605ffd83dbSDimitry Andric getSubtargetInfo()); 6618bcb0991SDimitry Andric } 6628bcb0991SDimitry Andric 6630b57cec5SDimitry Andric void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) { 66481ad6265SDimitry Andric auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo(); 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric unsigned NumNOPBytes = MI.getOperand(1).getImm(); 6670b57cec5SDimitry Andric 668480093f4SDimitry Andric auto &Ctx = OutStreamer->getContext(); 669480093f4SDimitry Andric MCSymbol *MILabel = Ctx.createTempSymbol(); 6705ffd83dbSDimitry Andric OutStreamer->emitLabel(MILabel); 671480093f4SDimitry Andric 672480093f4SDimitry Andric SM.recordStackMap(*MILabel, MI); 6730b57cec5SDimitry Andric assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!"); 6740b57cec5SDimitry Andric 6750b57cec5SDimitry Andric // Scan ahead to trim the shadow. 6760b57cec5SDimitry Andric unsigned ShadowBytes = 0; 6770b57cec5SDimitry Andric const MachineBasicBlock &MBB = *MI.getParent(); 6780b57cec5SDimitry Andric MachineBasicBlock::const_iterator MII(MI); 6790b57cec5SDimitry Andric ++MII; 6800b57cec5SDimitry Andric while (ShadowBytes < NumNOPBytes) { 6810b57cec5SDimitry Andric if (MII == MBB.end() || 6820b57cec5SDimitry Andric MII->getOpcode() == TargetOpcode::PATCHPOINT || 6830b57cec5SDimitry Andric MII->getOpcode() == TargetOpcode::STACKMAP) 6840b57cec5SDimitry Andric break; 6850b57cec5SDimitry Andric ShadowBytes += TII->getInstSizeInBytes(*MII); 6860b57cec5SDimitry Andric if (MII->isCall()) 6870b57cec5SDimitry Andric break; 6880b57cec5SDimitry Andric ++MII; 6890b57cec5SDimitry Andric } 6900b57cec5SDimitry Andric 6910b57cec5SDimitry Andric // Emit nops. 6920b57cec5SDimitry Andric while (ShadowBytes < NumNOPBytes) 6930b57cec5SDimitry Andric ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes, 6940b57cec5SDimitry Andric getSubtargetInfo()); 6950b57cec5SDimitry Andric } 6960b57cec5SDimitry Andric 6970b57cec5SDimitry Andric // Lower a patchpoint of the form: 6980b57cec5SDimitry Andric // [<def>], <id>, <numBytes>, <target>, <numArgs> 6990b57cec5SDimitry Andric void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI, 7000b57cec5SDimitry Andric SystemZMCInstLower &Lower) { 701480093f4SDimitry Andric auto &Ctx = OutStreamer->getContext(); 702480093f4SDimitry Andric MCSymbol *MILabel = Ctx.createTempSymbol(); 7035ffd83dbSDimitry Andric OutStreamer->emitLabel(MILabel); 704480093f4SDimitry Andric 705480093f4SDimitry Andric SM.recordPatchPoint(*MILabel, MI); 7060b57cec5SDimitry Andric PatchPointOpers Opers(&MI); 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric unsigned EncodedBytes = 0; 7090b57cec5SDimitry Andric const MachineOperand &CalleeMO = Opers.getCallTarget(); 7100b57cec5SDimitry Andric 7110b57cec5SDimitry Andric if (CalleeMO.isImm()) { 7120b57cec5SDimitry Andric uint64_t CallTarget = CalleeMO.getImm(); 7130b57cec5SDimitry Andric if (CallTarget) { 7140b57cec5SDimitry Andric unsigned ScratchIdx = -1; 7150b57cec5SDimitry Andric unsigned ScratchReg = 0; 7160b57cec5SDimitry Andric do { 7170b57cec5SDimitry Andric ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1); 7180b57cec5SDimitry Andric ScratchReg = MI.getOperand(ScratchIdx).getReg(); 7190b57cec5SDimitry Andric } while (ScratchReg == SystemZ::R0D); 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric // Materialize the call target address 7220b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF) 7230b57cec5SDimitry Andric .addReg(ScratchReg) 7240b57cec5SDimitry Andric .addImm(CallTarget & 0xFFFFFFFF)); 7250b57cec5SDimitry Andric EncodedBytes += 6; 7260b57cec5SDimitry Andric if (CallTarget >> 32) { 7270b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF) 7280b57cec5SDimitry Andric .addReg(ScratchReg) 7290b57cec5SDimitry Andric .addImm(CallTarget >> 32)); 7300b57cec5SDimitry Andric EncodedBytes += 6; 7310b57cec5SDimitry Andric } 7320b57cec5SDimitry Andric 7330b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 7340b57cec5SDimitry Andric .addReg(SystemZ::R14D) 7350b57cec5SDimitry Andric .addReg(ScratchReg)); 7360b57cec5SDimitry Andric EncodedBytes += 2; 7370b57cec5SDimitry Andric } 7380b57cec5SDimitry Andric } else if (CalleeMO.isGlobal()) { 7390b57cec5SDimitry Andric const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT); 7400b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL) 7410b57cec5SDimitry Andric .addReg(SystemZ::R14D) 7420b57cec5SDimitry Andric .addExpr(Expr)); 7430b57cec5SDimitry Andric EncodedBytes += 6; 7440b57cec5SDimitry Andric } 7450b57cec5SDimitry Andric 7460b57cec5SDimitry Andric // Emit padding. 7470b57cec5SDimitry Andric unsigned NumBytes = Opers.getNumPatchBytes(); 7480b57cec5SDimitry Andric assert(NumBytes >= EncodedBytes && 7490b57cec5SDimitry Andric "Patchpoint can't request size less than the length of a call."); 7500b57cec5SDimitry Andric assert((NumBytes - EncodedBytes) % 2 == 0 && 7510b57cec5SDimitry Andric "Invalid number of NOP bytes requested!"); 7520b57cec5SDimitry Andric while (EncodedBytes < NumBytes) 7530b57cec5SDimitry Andric EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes, 7540b57cec5SDimitry Andric getSubtargetInfo()); 7550b57cec5SDimitry Andric } 7560b57cec5SDimitry Andric 757*bdd1243dSDimitry Andric // The *alignment* of 128-bit vector types is different between the software 758*bdd1243dSDimitry Andric // and hardware vector ABIs. If the there is an externally visible use of a 759*bdd1243dSDimitry Andric // vector type in the module it should be annotated with an attribute. 760*bdd1243dSDimitry Andric void SystemZAsmPrinter::emitAttributes(Module &M) { 761*bdd1243dSDimitry Andric if (M.getModuleFlag("s390x-visible-vector-ABI")) { 762*bdd1243dSDimitry Andric bool HasVectorFeature = 763*bdd1243dSDimitry Andric TM.getMCSubtargetInfo()->getFeatureBits()[SystemZ::FeatureVector]; 764*bdd1243dSDimitry Andric OutStreamer->emitGNUAttribute(8, HasVectorFeature ? 2 : 1); 765*bdd1243dSDimitry Andric } 766*bdd1243dSDimitry Andric } 767*bdd1243dSDimitry Andric 7680b57cec5SDimitry Andric // Convert a SystemZ-specific constant pool modifier into the associated 7690b57cec5SDimitry Andric // MCSymbolRefExpr variant kind. 7700b57cec5SDimitry Andric static MCSymbolRefExpr::VariantKind 7710b57cec5SDimitry Andric getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) { 7720b57cec5SDimitry Andric switch (Modifier) { 7730b57cec5SDimitry Andric case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD; 7740b57cec5SDimitry Andric case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM; 7750b57cec5SDimitry Andric case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF; 7760b57cec5SDimitry Andric case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF; 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric llvm_unreachable("Invalid SystemCPModifier!"); 7790b57cec5SDimitry Andric } 7800b57cec5SDimitry Andric 7815ffd83dbSDimitry Andric void SystemZAsmPrinter::emitMachineConstantPoolValue( 7825ffd83dbSDimitry Andric MachineConstantPoolValue *MCPV) { 7830b57cec5SDimitry Andric auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV); 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric const MCExpr *Expr = 7860b57cec5SDimitry Andric MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()), 7870b57cec5SDimitry Andric getModifierVariantKind(ZCPV->getModifier()), 7880b57cec5SDimitry Andric OutContext); 7890b57cec5SDimitry Andric uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType()); 7900b57cec5SDimitry Andric 7915ffd83dbSDimitry Andric OutStreamer->emitValue(Expr, Size); 7920b57cec5SDimitry Andric } 7930b57cec5SDimitry Andric 794*bdd1243dSDimitry Andric static void printFormattedRegName(const MCAsmInfo *MAI, unsigned RegNo, 795*bdd1243dSDimitry Andric raw_ostream &OS) { 796*bdd1243dSDimitry Andric const char *RegName = SystemZInstPrinter::getRegisterName(RegNo); 797*bdd1243dSDimitry Andric if (MAI->getAssemblerDialect() == AD_HLASM) { 798*bdd1243dSDimitry Andric // Skip register prefix so that only register number is left 799*bdd1243dSDimitry Andric assert(isalpha(RegName[0]) && isdigit(RegName[1])); 800*bdd1243dSDimitry Andric OS << (RegName + 1); 801*bdd1243dSDimitry Andric } else 802*bdd1243dSDimitry Andric OS << '%' << RegName; 803*bdd1243dSDimitry Andric } 804*bdd1243dSDimitry Andric 805*bdd1243dSDimitry Andric static void printOperand(const MCOperand &MCOp, const MCAsmInfo *MAI, 806*bdd1243dSDimitry Andric raw_ostream &OS) { 807*bdd1243dSDimitry Andric if (MCOp.isReg()) { 808*bdd1243dSDimitry Andric if (!MCOp.getReg()) 809*bdd1243dSDimitry Andric OS << '0'; 810*bdd1243dSDimitry Andric else 811*bdd1243dSDimitry Andric printFormattedRegName(MAI, MCOp.getReg(), OS); 812*bdd1243dSDimitry Andric } else if (MCOp.isImm()) 813*bdd1243dSDimitry Andric OS << MCOp.getImm(); 814*bdd1243dSDimitry Andric else if (MCOp.isExpr()) 815*bdd1243dSDimitry Andric MCOp.getExpr()->print(OS, MAI); 816*bdd1243dSDimitry Andric else 817*bdd1243dSDimitry Andric llvm_unreachable("Invalid operand"); 818*bdd1243dSDimitry Andric } 819*bdd1243dSDimitry Andric 820*bdd1243dSDimitry Andric static void printAddress(const MCAsmInfo *MAI, unsigned Base, 821*bdd1243dSDimitry Andric const MCOperand &DispMO, unsigned Index, 822*bdd1243dSDimitry Andric raw_ostream &OS) { 823*bdd1243dSDimitry Andric printOperand(DispMO, MAI, OS); 824*bdd1243dSDimitry Andric if (Base || Index) { 825*bdd1243dSDimitry Andric OS << '('; 826*bdd1243dSDimitry Andric if (Index) { 827*bdd1243dSDimitry Andric printFormattedRegName(MAI, Index, OS); 828*bdd1243dSDimitry Andric if (Base) 829*bdd1243dSDimitry Andric OS << ','; 830*bdd1243dSDimitry Andric } 831*bdd1243dSDimitry Andric if (Base) 832*bdd1243dSDimitry Andric printFormattedRegName(MAI, Base, OS); 833*bdd1243dSDimitry Andric OS << ')'; 834*bdd1243dSDimitry Andric } 835*bdd1243dSDimitry Andric } 836*bdd1243dSDimitry Andric 8370b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 8380b57cec5SDimitry Andric const char *ExtraCode, 8390b57cec5SDimitry Andric raw_ostream &OS) { 840fe6060f1SDimitry Andric const MCRegisterInfo &MRI = *TM.getMCRegisterInfo(); 841fe6060f1SDimitry Andric const MachineOperand &MO = MI->getOperand(OpNo); 842fe6060f1SDimitry Andric MCOperand MCOp; 843fe6060f1SDimitry Andric if (ExtraCode) { 844fe6060f1SDimitry Andric if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() && 845fe6060f1SDimitry Andric SystemZ::GR128BitRegClass.contains(MO.getReg())) 846fe6060f1SDimitry Andric MCOp = 847fe6060f1SDimitry Andric MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64)); 848fe6060f1SDimitry Andric else 8490b57cec5SDimitry Andric return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS); 850fe6060f1SDimitry Andric } else { 8510b57cec5SDimitry Andric SystemZMCInstLower Lower(MF->getContext(), *this); 852fe6060f1SDimitry Andric MCOp = Lower.lowerOperand(MO); 853fe6060f1SDimitry Andric } 854*bdd1243dSDimitry Andric printOperand(MCOp, MAI, OS); 8550b57cec5SDimitry Andric return false; 8560b57cec5SDimitry Andric } 8570b57cec5SDimitry Andric 8580b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 8590b57cec5SDimitry Andric unsigned OpNo, 8600b57cec5SDimitry Andric const char *ExtraCode, 8610b57cec5SDimitry Andric raw_ostream &OS) { 862349cc55cSDimitry Andric printAddress(MAI, MI->getOperand(OpNo).getReg(), 863349cc55cSDimitry Andric MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()), 8640b57cec5SDimitry Andric MI->getOperand(OpNo + 2).getReg(), OS); 8650b57cec5SDimitry Andric return false; 8660b57cec5SDimitry Andric } 8670b57cec5SDimitry Andric 8685ffd83dbSDimitry Andric void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) { 869*bdd1243dSDimitry Andric emitAttributes(M); 8700b57cec5SDimitry Andric } 8710b57cec5SDimitry Andric 87281ad6265SDimitry Andric void SystemZAsmPrinter::emitFunctionBodyEnd() { 87381ad6265SDimitry Andric if (TM.getTargetTriple().isOSzOS()) { 87481ad6265SDimitry Andric // Emit symbol for the end of function if the z/OS target streamer 87581ad6265SDimitry Andric // is used. This is needed to calculate the size of the function. 87681ad6265SDimitry Andric MCSymbol *FnEndSym = createTempSymbol("func_end"); 87781ad6265SDimitry Andric OutStreamer->emitLabel(FnEndSym); 87881ad6265SDimitry Andric 87981ad6265SDimitry Andric OutStreamer->pushSection(); 88081ad6265SDimitry Andric OutStreamer->switchSection(getObjFileLowering().getPPA1Section()); 88181ad6265SDimitry Andric emitPPA1(FnEndSym); 88281ad6265SDimitry Andric OutStreamer->popSection(); 88381ad6265SDimitry Andric 88481ad6265SDimitry Andric CurrentFnPPA1Sym = nullptr; 88581ad6265SDimitry Andric CurrentFnEPMarkerSym = nullptr; 88681ad6265SDimitry Andric } 88781ad6265SDimitry Andric } 88881ad6265SDimitry Andric 88981ad6265SDimitry Andric static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg, 89081ad6265SDimitry Andric bool StackProtector, bool FPRMask, bool VRMask) { 89181ad6265SDimitry Andric enum class PPA1Flag1 : uint8_t { 89281ad6265SDimitry Andric DSA64Bit = (0x80 >> 0), 89381ad6265SDimitry Andric VarArg = (0x80 >> 7), 89481ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(DSA64Bit) 89581ad6265SDimitry Andric }; 89681ad6265SDimitry Andric enum class PPA1Flag2 : uint8_t { 89781ad6265SDimitry Andric ExternalProcedure = (0x80 >> 0), 89881ad6265SDimitry Andric STACKPROTECTOR = (0x80 >> 3), 89981ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure) 90081ad6265SDimitry Andric }; 90181ad6265SDimitry Andric enum class PPA1Flag3 : uint8_t { 90281ad6265SDimitry Andric FPRMask = (0x80 >> 2), 90381ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(FPRMask) 90481ad6265SDimitry Andric }; 90581ad6265SDimitry Andric enum class PPA1Flag4 : uint8_t { 90681ad6265SDimitry Andric EPMOffsetPresent = (0x80 >> 0), 90781ad6265SDimitry Andric VRMask = (0x80 >> 2), 90881ad6265SDimitry Andric ProcedureNamePresent = (0x80 >> 7), 90981ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent) 91081ad6265SDimitry Andric }; 91181ad6265SDimitry Andric 91281ad6265SDimitry Andric // Declare optional section flags that can be modified. 91381ad6265SDimitry Andric auto Flags1 = PPA1Flag1(0); 91481ad6265SDimitry Andric auto Flags2 = PPA1Flag2::ExternalProcedure; 91581ad6265SDimitry Andric auto Flags3 = PPA1Flag3(0); 91681ad6265SDimitry Andric auto Flags4 = PPA1Flag4::EPMOffsetPresent | PPA1Flag4::ProcedureNamePresent; 91781ad6265SDimitry Andric 91881ad6265SDimitry Andric Flags1 |= PPA1Flag1::DSA64Bit; 91981ad6265SDimitry Andric 92081ad6265SDimitry Andric if (VarArg) 92181ad6265SDimitry Andric Flags1 |= PPA1Flag1::VarArg; 92281ad6265SDimitry Andric 92381ad6265SDimitry Andric if (StackProtector) 92481ad6265SDimitry Andric Flags2 |= PPA1Flag2::STACKPROTECTOR; 92581ad6265SDimitry Andric 92681ad6265SDimitry Andric // SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in. 92781ad6265SDimitry Andric if (FPRMask) 92881ad6265SDimitry Andric Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag. 92981ad6265SDimitry Andric 93081ad6265SDimitry Andric if (VRMask) 93181ad6265SDimitry Andric Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag. 93281ad6265SDimitry Andric 93381ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 1"); 93481ad6265SDimitry Andric if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit) 93581ad6265SDimitry Andric OutStreamer->AddComment(" Bit 0: 1 = 64-bit DSA"); 93681ad6265SDimitry Andric else 93781ad6265SDimitry Andric OutStreamer->AddComment(" Bit 0: 0 = 32-bit DSA"); 93881ad6265SDimitry Andric if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg) 93981ad6265SDimitry Andric OutStreamer->AddComment(" Bit 7: 1 = Vararg function"); 94081ad6265SDimitry Andric OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1. 94181ad6265SDimitry Andric 94281ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 2"); 94381ad6265SDimitry Andric if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure) 94481ad6265SDimitry Andric OutStreamer->AddComment(" Bit 0: 1 = External procedure"); 94581ad6265SDimitry Andric if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR) 94681ad6265SDimitry Andric OutStreamer->AddComment(" Bit 3: 1 = STACKPROTECT is enabled"); 94781ad6265SDimitry Andric else 94881ad6265SDimitry Andric OutStreamer->AddComment(" Bit 3: 0 = STACKPROTECT is not enabled"); 94981ad6265SDimitry Andric OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2. 95081ad6265SDimitry Andric 95181ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 3"); 95281ad6265SDimitry Andric if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask) 95381ad6265SDimitry Andric OutStreamer->AddComment(" Bit 2: 1 = FP Reg Mask is in optional area"); 95481ad6265SDimitry Andric OutStreamer->emitInt8( 95581ad6265SDimitry Andric static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections). 95681ad6265SDimitry Andric 95781ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 4"); 95881ad6265SDimitry Andric if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask) 95981ad6265SDimitry Andric OutStreamer->AddComment(" Bit 2: 1 = Vector Reg Mask is in optional area"); 96081ad6265SDimitry Andric OutStreamer->emitInt8(static_cast<uint8_t>( 96181ad6265SDimitry Andric Flags4)); // Flags 4 (optional sections, always emit these). 96281ad6265SDimitry Andric } 96381ad6265SDimitry Andric 96481ad6265SDimitry Andric void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) { 96581ad6265SDimitry Andric const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo(); 96681ad6265SDimitry Andric const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 96781ad6265SDimitry Andric const auto TargetHasVector = Subtarget.hasVector(); 96881ad6265SDimitry Andric 96981ad6265SDimitry Andric const SystemZMachineFunctionInfo *ZFI = 97081ad6265SDimitry Andric MF->getInfo<SystemZMachineFunctionInfo>(); 97181ad6265SDimitry Andric const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>( 97281ad6265SDimitry Andric Subtarget.getFrameLowering()); 97381ad6265SDimitry Andric const MachineFrameInfo &MFFrame = MF->getFrameInfo(); 97481ad6265SDimitry Andric 97581ad6265SDimitry Andric // Get saved GPR/FPR/VPR masks. 97681ad6265SDimitry Andric const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo(); 97781ad6265SDimitry Andric uint16_t SavedGPRMask = 0; 97881ad6265SDimitry Andric uint16_t SavedFPRMask = 0; 97981ad6265SDimitry Andric uint8_t SavedVRMask = 0; 98081ad6265SDimitry Andric int64_t OffsetFPR = 0; 98181ad6265SDimitry Andric int64_t OffsetVR = 0; 98281ad6265SDimitry Andric const int64_t TopOfStack = 98381ad6265SDimitry Andric MFFrame.getOffsetAdjustment() + MFFrame.getStackSize(); 98481ad6265SDimitry Andric 98581ad6265SDimitry Andric // Loop over the spilled registers. The CalleeSavedInfo can't be used because 98681ad6265SDimitry Andric // it does not contain all spilled registers. 98781ad6265SDimitry Andric for (unsigned I = ZFI->getSpillGPRRegs().LowGPR, 98881ad6265SDimitry Andric E = ZFI->getSpillGPRRegs().HighGPR; 98981ad6265SDimitry Andric I && E && I <= E; ++I) { 99081ad6265SDimitry Andric unsigned V = TRI->getEncodingValue((Register)I); 99181ad6265SDimitry Andric assert(V < 16 && "GPR index out of range"); 99281ad6265SDimitry Andric SavedGPRMask |= 1 << (15 - V); 99381ad6265SDimitry Andric } 99481ad6265SDimitry Andric 99581ad6265SDimitry Andric for (auto &CS : CSI) { 99681ad6265SDimitry Andric unsigned Reg = CS.getReg(); 99781ad6265SDimitry Andric unsigned I = TRI->getEncodingValue(Reg); 99881ad6265SDimitry Andric 99981ad6265SDimitry Andric if (SystemZ::FP64BitRegClass.contains(Reg)) { 100081ad6265SDimitry Andric assert(I < 16 && "FPR index out of range"); 100181ad6265SDimitry Andric SavedFPRMask |= 1 << (15 - I); 100281ad6265SDimitry Andric int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx()); 100381ad6265SDimitry Andric if (Temp < OffsetFPR) 100481ad6265SDimitry Andric OffsetFPR = Temp; 100581ad6265SDimitry Andric } else if (SystemZ::VR128BitRegClass.contains(Reg)) { 100681ad6265SDimitry Andric assert(I >= 16 && I <= 23 && "VPR index out of range"); 100781ad6265SDimitry Andric unsigned BitNum = I - 16; 100881ad6265SDimitry Andric SavedVRMask |= 1 << (7 - BitNum); 100981ad6265SDimitry Andric int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx()); 101081ad6265SDimitry Andric if (Temp < OffsetVR) 101181ad6265SDimitry Andric OffsetVR = Temp; 101281ad6265SDimitry Andric } 101381ad6265SDimitry Andric } 101481ad6265SDimitry Andric 101581ad6265SDimitry Andric // Adjust the offset. 101681ad6265SDimitry Andric OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0; 101781ad6265SDimitry Andric OffsetVR += (OffsetVR < 0) ? TopOfStack : 0; 101881ad6265SDimitry Andric 101981ad6265SDimitry Andric // Get alloca register. 102081ad6265SDimitry Andric uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF)); 102181ad6265SDimitry Andric uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0; 102281ad6265SDimitry Andric assert(AllocaReg < 16 && "Can't have alloca register larger than 15"); 102381ad6265SDimitry Andric (void)AllocaReg; 102481ad6265SDimitry Andric 102581ad6265SDimitry Andric // Build FPR save area offset. 102681ad6265SDimitry Andric uint32_t FrameAndFPROffset = 0; 102781ad6265SDimitry Andric if (SavedFPRMask) { 102881ad6265SDimitry Andric uint64_t FPRSaveAreaOffset = OffsetFPR; 102981ad6265SDimitry Andric assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range"); 103081ad6265SDimitry Andric 103181ad6265SDimitry Andric FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits. 103281ad6265SDimitry Andric FrameAndFPROffset |= FrameReg << 28; // Put into top 4 bits. 103381ad6265SDimitry Andric } 103481ad6265SDimitry Andric 103581ad6265SDimitry Andric // Build VR save area offset. 103681ad6265SDimitry Andric uint32_t FrameAndVROffset = 0; 103781ad6265SDimitry Andric if (TargetHasVector && SavedVRMask) { 103881ad6265SDimitry Andric uint64_t VRSaveAreaOffset = OffsetVR; 103981ad6265SDimitry Andric assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range"); 104081ad6265SDimitry Andric 104181ad6265SDimitry Andric FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits. 104281ad6265SDimitry Andric FrameAndVROffset |= FrameReg << 28; // Put into top 4 bits. 104381ad6265SDimitry Andric } 104481ad6265SDimitry Andric 104581ad6265SDimitry Andric // Emit PPA1 section. 104681ad6265SDimitry Andric OutStreamer->AddComment("PPA1"); 104781ad6265SDimitry Andric OutStreamer->emitLabel(CurrentFnPPA1Sym); 104881ad6265SDimitry Andric OutStreamer->AddComment("Version"); 104981ad6265SDimitry Andric OutStreamer->emitInt8(0x02); // Version. 105081ad6265SDimitry Andric OutStreamer->AddComment("LE Signature X'CE'"); 105181ad6265SDimitry Andric OutStreamer->emitInt8(0xCE); // CEL signature. 105281ad6265SDimitry Andric OutStreamer->AddComment("Saved GPR Mask"); 105381ad6265SDimitry Andric OutStreamer->emitInt16(SavedGPRMask); 105481ad6265SDimitry Andric 105581ad6265SDimitry Andric emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(), 105681ad6265SDimitry Andric MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0, 105781ad6265SDimitry Andric TargetHasVector && SavedVRMask != 0); 105881ad6265SDimitry Andric 105981ad6265SDimitry Andric OutStreamer->AddComment("Length/4 of Parms"); 106081ad6265SDimitry Andric OutStreamer->emitInt16( 106181ad6265SDimitry Andric static_cast<uint16_t>(MFFrame.getMaxCallFrameSize() / 4)); // Parms/4. 106281ad6265SDimitry Andric OutStreamer->AddComment("Length of Code"); 106381ad6265SDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4); 106481ad6265SDimitry Andric 106581ad6265SDimitry Andric // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3). 106681ad6265SDimitry Andric if (SavedFPRMask) { 106781ad6265SDimitry Andric OutStreamer->AddComment("FPR mask"); 106881ad6265SDimitry Andric OutStreamer->emitInt16(SavedFPRMask); 106981ad6265SDimitry Andric OutStreamer->AddComment("AR mask"); 107081ad6265SDimitry Andric OutStreamer->emitInt16(0); // AR Mask, unused currently. 107181ad6265SDimitry Andric OutStreamer->AddComment("FPR Save Area Locator"); 107281ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 0-3: Register R") 107381ad6265SDimitry Andric .concat(utostr(FrameAndFPROffset >> 28)) 107481ad6265SDimitry Andric .str()); 107581ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 4-31: Offset ") 107681ad6265SDimitry Andric .concat(utostr(FrameAndFPROffset & 0x0FFFFFFF)) 107781ad6265SDimitry Andric .str()); 107881ad6265SDimitry Andric OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with 107981ad6265SDimitry Andric // register to add value to 108081ad6265SDimitry Andric // (alloca reg). 108181ad6265SDimitry Andric } 108281ad6265SDimitry Andric 108381ad6265SDimitry Andric // Emit saved VR mask to VR save area. 108481ad6265SDimitry Andric if (TargetHasVector && SavedVRMask) { 108581ad6265SDimitry Andric OutStreamer->AddComment("VR mask"); 108681ad6265SDimitry Andric OutStreamer->emitInt8(SavedVRMask); 108781ad6265SDimitry Andric OutStreamer->emitInt8(0); // Reserved. 108881ad6265SDimitry Andric OutStreamer->emitInt16(0); // Also reserved. 108981ad6265SDimitry Andric OutStreamer->AddComment("VR Save Area Locator"); 109081ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 0-3: Register R") 109181ad6265SDimitry Andric .concat(utostr(FrameAndVROffset >> 28)) 109281ad6265SDimitry Andric .str()); 109381ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 4-31: Offset ") 109481ad6265SDimitry Andric .concat(utostr(FrameAndVROffset & 0x0FFFFFFF)) 109581ad6265SDimitry Andric .str()); 109681ad6265SDimitry Andric OutStreamer->emitInt32(FrameAndVROffset); 109781ad6265SDimitry Andric } 109881ad6265SDimitry Andric 109981ad6265SDimitry Andric // Emit offset to entry point optional section (0x80 of flags 4). 110081ad6265SDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym, 110181ad6265SDimitry Andric 4); 110281ad6265SDimitry Andric } 110381ad6265SDimitry Andric 110404eeddc0SDimitry Andric void SystemZAsmPrinter::emitFunctionEntryLabel() { 110581ad6265SDimitry Andric const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 110604eeddc0SDimitry Andric 110704eeddc0SDimitry Andric if (Subtarget.getTargetTriple().isOSzOS()) { 110804eeddc0SDimitry Andric MCContext &OutContext = OutStreamer->getContext(); 110981ad6265SDimitry Andric 111081ad6265SDimitry Andric // Save information for later use. 111181ad6265SDimitry Andric std::string N(MF->getFunction().hasName() 111281ad6265SDimitry Andric ? Twine(MF->getFunction().getName()).concat("_").str() 111381ad6265SDimitry Andric : ""); 111481ad6265SDimitry Andric 111581ad6265SDimitry Andric CurrentFnEPMarkerSym = 111681ad6265SDimitry Andric OutContext.createTempSymbol(Twine("EPM_").concat(N).str(), true); 111781ad6265SDimitry Andric CurrentFnPPA1Sym = 111881ad6265SDimitry Andric OutContext.createTempSymbol(Twine("PPA1_").concat(N).str(), true); 111904eeddc0SDimitry Andric 112004eeddc0SDimitry Andric // EntryPoint Marker 112104eeddc0SDimitry Andric const MachineFrameInfo &MFFrame = MF->getFrameInfo(); 112204eeddc0SDimitry Andric bool IsUsingAlloca = MFFrame.hasVarSizedObjects(); 112304eeddc0SDimitry Andric 112404eeddc0SDimitry Andric // Set Flags 112504eeddc0SDimitry Andric uint8_t Flags = 0; 112604eeddc0SDimitry Andric if (IsUsingAlloca) 112704eeddc0SDimitry Andric Flags |= 0x04; 112804eeddc0SDimitry Andric 112904eeddc0SDimitry Andric uint32_t DSASize = MFFrame.getStackSize(); 113004eeddc0SDimitry Andric 113104eeddc0SDimitry Andric // Combine into top 27 bits of DSASize and bottom 5 bits of Flags. 113204eeddc0SDimitry Andric uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5 113304eeddc0SDimitry Andric DSAAndFlags |= Flags; 113404eeddc0SDimitry Andric 113504eeddc0SDimitry Andric // Emit entry point marker section. 113604eeddc0SDimitry Andric OutStreamer->AddComment("XPLINK Routine Layout Entry"); 113781ad6265SDimitry Andric OutStreamer->emitLabel(CurrentFnEPMarkerSym); 113804eeddc0SDimitry Andric OutStreamer->AddComment("Eyecatcher 0x00C300C500C500"); 113904eeddc0SDimitry Andric OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher. 114004eeddc0SDimitry Andric OutStreamer->AddComment("Mark Type C'1'"); 114104eeddc0SDimitry Andric OutStreamer->emitInt8(0xF1); // Mark Type. 114281ad6265SDimitry Andric OutStreamer->AddComment("Offset to PPA1"); 114381ad6265SDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(CurrentFnPPA1Sym, CurrentFnEPMarkerSym, 114481ad6265SDimitry Andric 4); 114504eeddc0SDimitry Andric if (OutStreamer->isVerboseAsm()) { 114604eeddc0SDimitry Andric OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize)); 114704eeddc0SDimitry Andric OutStreamer->AddComment("Entry Flags"); 114804eeddc0SDimitry Andric if (Flags & 0x04) 114904eeddc0SDimitry Andric OutStreamer->AddComment(" Bit 2: 1 = Uses alloca"); 115004eeddc0SDimitry Andric else 115104eeddc0SDimitry Andric OutStreamer->AddComment(" Bit 2: 0 = Does not use alloca"); 115204eeddc0SDimitry Andric } 115304eeddc0SDimitry Andric OutStreamer->emitInt32(DSAAndFlags); 115404eeddc0SDimitry Andric } 115504eeddc0SDimitry Andric 115604eeddc0SDimitry Andric AsmPrinter::emitFunctionEntryLabel(); 115704eeddc0SDimitry Andric } 115804eeddc0SDimitry Andric 11590b57cec5SDimitry Andric // Force static initialization. 1160480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() { 11610b57cec5SDimitry Andric RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget()); 11620b57cec5SDimitry Andric } 1163