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" 16*06c3fb27SDimitry Andric #include "MCTargetDesc/SystemZMCExpr.h" 170b57cec5SDimitry Andric #include "SystemZConstantPoolValue.h" 180b57cec5SDimitry Andric #include "SystemZMCInstLower.h" 190b57cec5SDimitry Andric #include "TargetInfo/SystemZTargetInfo.h" 20*06c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h" 21480093f4SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 240b57cec5SDimitry Andric #include "llvm/IR/Mangler.h" 250b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 260b57cec5SDimitry Andric #include "llvm/MC/MCInstBuilder.h" 27480093f4SDimitry Andric #include "llvm/MC/MCSectionELF.h" 280b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 29349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric using namespace llvm; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the 340b57cec5SDimitry Andric // GR64 register operands turned into GR32s. 350b57cec5SDimitry Andric static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) { 360b57cec5SDimitry Andric if (MI->isCompare()) 370b57cec5SDimitry Andric return MCInstBuilder(Opcode) 380b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 390b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()); 400b57cec5SDimitry Andric else 410b57cec5SDimitry Andric return MCInstBuilder(Opcode) 420b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 430b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg())) 440b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()); 450b57cec5SDimitry Andric } 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the 480b57cec5SDimitry Andric // GR64 register operands turned into GRH32s. 490b57cec5SDimitry Andric static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) { 500b57cec5SDimitry Andric if (MI->isCompare()) 510b57cec5SDimitry Andric return MCInstBuilder(Opcode) 520b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 530b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()); 540b57cec5SDimitry Andric else 550b57cec5SDimitry Andric return MCInstBuilder(Opcode) 560b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 570b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg())) 580b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()); 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the 620b57cec5SDimitry Andric // R2 register turned into a GR64. 630b57cec5SDimitry Andric static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) { 640b57cec5SDimitry Andric return MCInstBuilder(Opcode) 650b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 660b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 670b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())) 680b57cec5SDimitry Andric .addImm(MI->getOperand(3).getImm()) 690b57cec5SDimitry Andric .addImm(MI->getOperand(4).getImm()) 700b57cec5SDimitry Andric .addImm(MI->getOperand(5).getImm()); 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) { 740b57cec5SDimitry Andric StringRef Name = "__tls_get_offset"; 750b57cec5SDimitry Andric return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name), 760b57cec5SDimitry Andric MCSymbolRefExpr::VK_PLT, 770b57cec5SDimitry Andric Context); 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) { 810b57cec5SDimitry Andric StringRef Name = "_GLOBAL_OFFSET_TABLE_"; 820b57cec5SDimitry Andric return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name), 830b57cec5SDimitry Andric MCSymbolRefExpr::VK_None, 840b57cec5SDimitry Andric Context); 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric // MI is an instruction that accepts an optional alignment hint, 880b57cec5SDimitry Andric // and which was already lowered to LoweredMI. If the alignment 890b57cec5SDimitry Andric // of the original memory operand is known, update LoweredMI to 900b57cec5SDimitry Andric // an instruction with the corresponding hint set. 910b57cec5SDimitry Andric static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI, 920b57cec5SDimitry Andric unsigned Opcode) { 9381ad6265SDimitry Andric if (MI->memoperands_empty()) 940b57cec5SDimitry Andric return; 9581ad6265SDimitry Andric 9681ad6265SDimitry Andric Align Alignment = Align(16); 9781ad6265SDimitry Andric for (MachineInstr::mmo_iterator MMOI = MI->memoperands_begin(), 9881ad6265SDimitry Andric EE = MI->memoperands_end(); MMOI != EE; ++MMOI) 9981ad6265SDimitry Andric if ((*MMOI)->getAlign() < Alignment) 10081ad6265SDimitry Andric Alignment = (*MMOI)->getAlign(); 10181ad6265SDimitry Andric 1020b57cec5SDimitry Andric unsigned AlignmentHint = 0; 10381ad6265SDimitry Andric if (Alignment >= Align(16)) 1040b57cec5SDimitry Andric AlignmentHint = 4; 10581ad6265SDimitry Andric else if (Alignment >= Align(8)) 1060b57cec5SDimitry Andric AlignmentHint = 3; 1070b57cec5SDimitry Andric if (AlignmentHint == 0) 1080b57cec5SDimitry Andric return; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric LoweredMI.setOpcode(Opcode); 1110b57cec5SDimitry Andric LoweredMI.addOperand(MCOperand::createImm(AlignmentHint)); 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric // MI loads the high part of a vector from memory. Return an instruction 1150b57cec5SDimitry Andric // that uses replicating vector load Opcode to do the same thing. 1160b57cec5SDimitry Andric static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) { 1170b57cec5SDimitry Andric return MCInstBuilder(Opcode) 1180b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 1190b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 1200b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 1210b57cec5SDimitry Andric .addReg(MI->getOperand(3).getReg()); 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric // MI stores the high part of a vector to memory. Return an instruction 1250b57cec5SDimitry Andric // that uses elemental vector store Opcode to do the same thing. 1260b57cec5SDimitry Andric static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) { 1270b57cec5SDimitry Andric return MCInstBuilder(Opcode) 1280b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 1290b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 1300b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 1310b57cec5SDimitry Andric .addReg(MI->getOperand(3).getReg()) 1320b57cec5SDimitry Andric .addImm(0); 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 13581ad6265SDimitry Andric // The XPLINK ABI requires that a no-op encoding the call type is emitted after 13681ad6265SDimitry Andric // each call to a subroutine. This information can be used by the called 13781ad6265SDimitry Andric // function to determine its entry point, e.g. for generating a backtrace. The 13881ad6265SDimitry Andric // call type is encoded as a register number in the bcr instruction. See 13981ad6265SDimitry Andric // enumeration CallType for the possible values. 14081ad6265SDimitry Andric void SystemZAsmPrinter::emitCallInformation(CallType CT) { 14181ad6265SDimitry Andric EmitToStreamer(*OutStreamer, 14281ad6265SDimitry Andric MCInstBuilder(SystemZ::BCRAsm) 14381ad6265SDimitry Andric .addImm(0) 14481ad6265SDimitry Andric .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)])); 14581ad6265SDimitry Andric } 14681ad6265SDimitry Andric 147*06c3fb27SDimitry Andric uint32_t SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MCSymbol *Sym, 148*06c3fb27SDimitry Andric unsigned SlotKind) { 149*06c3fb27SDimitry Andric auto Key = std::make_pair(Sym, SlotKind); 150*06c3fb27SDimitry Andric auto It = Displacements.find(Key); 151*06c3fb27SDimitry Andric 152*06c3fb27SDimitry Andric if (It != Displacements.end()) 153*06c3fb27SDimitry Andric return (*It).second; 154*06c3fb27SDimitry Andric 155*06c3fb27SDimitry Andric // Determine length of descriptor. 156*06c3fb27SDimitry Andric uint32_t Length; 157*06c3fb27SDimitry Andric switch (SlotKind) { 158*06c3fb27SDimitry Andric case SystemZII::MO_ADA_DIRECT_FUNC_DESC: 159*06c3fb27SDimitry Andric Length = 2 * PointerSize; 160*06c3fb27SDimitry Andric break; 161*06c3fb27SDimitry Andric default: 162*06c3fb27SDimitry Andric Length = PointerSize; 163*06c3fb27SDimitry Andric break; 164*06c3fb27SDimitry Andric } 165*06c3fb27SDimitry Andric 166*06c3fb27SDimitry Andric uint32_t Displacement = NextDisplacement; 167*06c3fb27SDimitry Andric Displacements[std::make_pair(Sym, SlotKind)] = NextDisplacement; 168*06c3fb27SDimitry Andric NextDisplacement += Length; 169*06c3fb27SDimitry Andric 170*06c3fb27SDimitry Andric return Displacement; 171*06c3fb27SDimitry Andric } 172*06c3fb27SDimitry Andric 173*06c3fb27SDimitry Andric uint32_t 174*06c3fb27SDimitry Andric SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MachineOperand MO) { 175*06c3fb27SDimitry Andric MCSymbol *Sym; 176*06c3fb27SDimitry Andric if (MO.getType() == MachineOperand::MO_GlobalAddress) { 177*06c3fb27SDimitry Andric const GlobalValue *GV = MO.getGlobal(); 178*06c3fb27SDimitry Andric Sym = MO.getParent()->getMF()->getTarget().getSymbol(GV); 179*06c3fb27SDimitry Andric assert(Sym && "No symbol"); 180*06c3fb27SDimitry Andric } else if (MO.getType() == MachineOperand::MO_ExternalSymbol) { 181*06c3fb27SDimitry Andric const char *SymName = MO.getSymbolName(); 182*06c3fb27SDimitry Andric Sym = MO.getParent()->getMF()->getContext().getOrCreateSymbol(SymName); 183*06c3fb27SDimitry Andric assert(Sym && "No symbol"); 184*06c3fb27SDimitry Andric } else 185*06c3fb27SDimitry Andric llvm_unreachable("Unexpected operand type"); 186*06c3fb27SDimitry Andric 187*06c3fb27SDimitry Andric unsigned ADAslotType = MO.getTargetFlags(); 188*06c3fb27SDimitry Andric return insert(Sym, ADAslotType); 189*06c3fb27SDimitry Andric } 190*06c3fb27SDimitry Andric 1915ffd83dbSDimitry Andric void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) { 192753f127fSDimitry Andric SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(), 193753f127fSDimitry Andric getSubtargetInfo().getFeatureBits()); 194753f127fSDimitry Andric 1950b57cec5SDimitry Andric SystemZMCInstLower Lower(MF->getContext(), *this); 1960b57cec5SDimitry Andric MCInst LoweredMI; 1970b57cec5SDimitry Andric switch (MI->getOpcode()) { 1980b57cec5SDimitry Andric case SystemZ::Return: 19981ad6265SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BR) 20081ad6265SDimitry Andric .addReg(SystemZ::R14D); 20181ad6265SDimitry Andric break; 20281ad6265SDimitry Andric 20381ad6265SDimitry Andric case SystemZ::Return_XPLINK: 20481ad6265SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::B) 20581ad6265SDimitry Andric .addReg(SystemZ::R7D) 20681ad6265SDimitry Andric .addImm(2) 20781ad6265SDimitry Andric .addReg(0); 2080b57cec5SDimitry Andric break; 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric case SystemZ::CondReturn: 2110b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BCR) 2120b57cec5SDimitry Andric .addImm(MI->getOperand(0).getImm()) 2130b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2140b57cec5SDimitry Andric .addReg(SystemZ::R14D); 2150b57cec5SDimitry Andric break; 2160b57cec5SDimitry Andric 21781ad6265SDimitry Andric case SystemZ::CondReturn_XPLINK: 21881ad6265SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BC) 21981ad6265SDimitry Andric .addImm(MI->getOperand(0).getImm()) 22081ad6265SDimitry Andric .addImm(MI->getOperand(1).getImm()) 22181ad6265SDimitry Andric .addReg(SystemZ::R7D) 22281ad6265SDimitry Andric .addImm(2) 22381ad6265SDimitry Andric .addReg(0); 22481ad6265SDimitry Andric break; 22581ad6265SDimitry Andric 2260b57cec5SDimitry Andric case SystemZ::CRBReturn: 2270b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CRB) 2280b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2290b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 2300b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2310b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2320b57cec5SDimitry Andric .addImm(0); 2330b57cec5SDimitry Andric break; 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric case SystemZ::CGRBReturn: 2360b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CGRB) 2370b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2380b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 2390b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2400b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2410b57cec5SDimitry Andric .addImm(0); 2420b57cec5SDimitry Andric break; 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric case SystemZ::CIBReturn: 2450b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CIB) 2460b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2470b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2480b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2490b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2500b57cec5SDimitry Andric .addImm(0); 2510b57cec5SDimitry Andric break; 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric case SystemZ::CGIBReturn: 2540b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CGIB) 2550b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2560b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2570b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2580b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2590b57cec5SDimitry Andric .addImm(0); 2600b57cec5SDimitry Andric break; 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric case SystemZ::CLRBReturn: 2630b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLRB) 2640b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2650b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 2660b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2670b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2680b57cec5SDimitry Andric .addImm(0); 2690b57cec5SDimitry Andric break; 2700b57cec5SDimitry Andric 2710b57cec5SDimitry Andric case SystemZ::CLGRBReturn: 2720b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLGRB) 2730b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2740b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 2750b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2760b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2770b57cec5SDimitry Andric .addImm(0); 2780b57cec5SDimitry Andric break; 2790b57cec5SDimitry Andric 2800b57cec5SDimitry Andric case SystemZ::CLIBReturn: 2810b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLIB) 2820b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2830b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2840b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2850b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2860b57cec5SDimitry Andric .addImm(0); 2870b57cec5SDimitry Andric break; 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric case SystemZ::CLGIBReturn: 2900b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLGIB) 2910b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2920b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2930b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2940b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2950b57cec5SDimitry Andric .addImm(0); 2960b57cec5SDimitry Andric break; 2970b57cec5SDimitry Andric 298fe6060f1SDimitry Andric case SystemZ::CallBRASL_XPLINK64: 299fe6060f1SDimitry Andric EmitToStreamer(*OutStreamer, 300fe6060f1SDimitry Andric MCInstBuilder(SystemZ::BRASL) 301fe6060f1SDimitry Andric .addReg(SystemZ::R7D) 302fe6060f1SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), 303fe6060f1SDimitry Andric MCSymbolRefExpr::VK_PLT))); 30481ad6265SDimitry Andric emitCallInformation(CallType::BRASL7); 305fe6060f1SDimitry Andric return; 306fe6060f1SDimitry Andric 307fe6060f1SDimitry Andric case SystemZ::CallBASR_XPLINK64: 308fe6060f1SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 309fe6060f1SDimitry Andric .addReg(SystemZ::R7D) 310fe6060f1SDimitry Andric .addReg(MI->getOperand(0).getReg())); 31181ad6265SDimitry Andric emitCallInformation(CallType::BASR76); 31281ad6265SDimitry Andric return; 31381ad6265SDimitry Andric 31481ad6265SDimitry Andric case SystemZ::CallBASR_STACKEXT: 31581ad6265SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 31681ad6265SDimitry Andric .addReg(SystemZ::R3D) 31781ad6265SDimitry Andric .addReg(MI->getOperand(0).getReg())); 31881ad6265SDimitry Andric emitCallInformation(CallType::BASR33); 319fe6060f1SDimitry Andric return; 320fe6060f1SDimitry Andric 321*06c3fb27SDimitry Andric case SystemZ::ADA_ENTRY_VALUE: 322*06c3fb27SDimitry Andric case SystemZ::ADA_ENTRY: { 323*06c3fb27SDimitry Andric const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 324*06c3fb27SDimitry Andric const SystemZInstrInfo *TII = Subtarget.getInstrInfo(); 325*06c3fb27SDimitry Andric uint32_t Disp = ADATable.insert(MI->getOperand(1)); 326*06c3fb27SDimitry Andric Register TargetReg = MI->getOperand(0).getReg(); 327*06c3fb27SDimitry Andric 328*06c3fb27SDimitry Andric Register ADAReg = MI->getOperand(2).getReg(); 329*06c3fb27SDimitry Andric Disp += MI->getOperand(3).getImm(); 330*06c3fb27SDimitry Andric bool LoadAddr = MI->getOpcode() == SystemZ::ADA_ENTRY; 331*06c3fb27SDimitry Andric 332*06c3fb27SDimitry Andric unsigned Op0 = LoadAddr ? SystemZ::LA : SystemZ::LG; 333*06c3fb27SDimitry Andric unsigned Op = TII->getOpcodeForOffset(Op0, Disp); 334*06c3fb27SDimitry Andric 335*06c3fb27SDimitry Andric Register IndexReg = 0; 336*06c3fb27SDimitry Andric if (!Op) { 337*06c3fb27SDimitry Andric if (TargetReg != ADAReg) { 338*06c3fb27SDimitry Andric IndexReg = TargetReg; 339*06c3fb27SDimitry Andric // Use TargetReg to store displacement. 340*06c3fb27SDimitry Andric EmitToStreamer( 341*06c3fb27SDimitry Andric *OutStreamer, 342*06c3fb27SDimitry Andric MCInstBuilder(SystemZ::LLILF).addReg(TargetReg).addImm(Disp)); 343*06c3fb27SDimitry Andric } else 344*06c3fb27SDimitry Andric EmitToStreamer( 345*06c3fb27SDimitry Andric *OutStreamer, 346*06c3fb27SDimitry Andric MCInstBuilder(SystemZ::ALGFI).addReg(TargetReg).addImm(Disp)); 347*06c3fb27SDimitry Andric Disp = 0; 348*06c3fb27SDimitry Andric Op = Op0; 349*06c3fb27SDimitry Andric } 350*06c3fb27SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(Op) 351*06c3fb27SDimitry Andric .addReg(TargetReg) 352*06c3fb27SDimitry Andric .addReg(IndexReg) 353*06c3fb27SDimitry Andric .addImm(Disp) 354*06c3fb27SDimitry Andric .addReg(ADAReg)); 355*06c3fb27SDimitry Andric 356*06c3fb27SDimitry Andric return; 357*06c3fb27SDimitry Andric } 3580b57cec5SDimitry Andric case SystemZ::CallBRASL: 3590b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRASL) 3600b57cec5SDimitry Andric .addReg(SystemZ::R14D) 3610b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 3620b57cec5SDimitry Andric break; 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric case SystemZ::CallBASR: 3650b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BASR) 3660b57cec5SDimitry Andric .addReg(SystemZ::R14D) 3670b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()); 3680b57cec5SDimitry Andric break; 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric case SystemZ::CallJG: 3710b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::JG) 3720b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 3730b57cec5SDimitry Andric break; 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric case SystemZ::CallBRCL: 3760b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRCL) 3770b57cec5SDimitry Andric .addImm(MI->getOperand(0).getImm()) 3780b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 3790b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT)); 3800b57cec5SDimitry Andric break; 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric case SystemZ::CallBR: 383e8d8bef9SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BR) 384e8d8bef9SDimitry Andric .addReg(MI->getOperand(0).getReg()); 3850b57cec5SDimitry Andric break; 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric case SystemZ::CallBCR: 3880b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BCR) 3890b57cec5SDimitry Andric .addImm(MI->getOperand(0).getImm()) 3900b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 391e8d8bef9SDimitry Andric .addReg(MI->getOperand(2).getReg()); 3920b57cec5SDimitry Andric break; 3930b57cec5SDimitry Andric 3940b57cec5SDimitry Andric case SystemZ::CRBCall: 3950b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CRB) 3960b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 3970b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 3980b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 399e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 4000b57cec5SDimitry Andric .addImm(0); 4010b57cec5SDimitry Andric break; 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric case SystemZ::CGRBCall: 4040b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CGRB) 4050b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4060b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 4070b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 408e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 4090b57cec5SDimitry Andric .addImm(0); 4100b57cec5SDimitry Andric break; 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric case SystemZ::CIBCall: 4130b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CIB) 4140b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4150b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 4160b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 417e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 4180b57cec5SDimitry Andric .addImm(0); 4190b57cec5SDimitry Andric break; 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric case SystemZ::CGIBCall: 4220b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CGIB) 4230b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4240b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 4250b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 426e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 4270b57cec5SDimitry Andric .addImm(0); 4280b57cec5SDimitry Andric break; 4290b57cec5SDimitry Andric 4300b57cec5SDimitry Andric case SystemZ::CLRBCall: 4310b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLRB) 4320b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4330b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 4340b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 435e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 4360b57cec5SDimitry Andric .addImm(0); 4370b57cec5SDimitry Andric break; 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric case SystemZ::CLGRBCall: 4400b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLGRB) 4410b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4420b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 4430b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 444e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 4450b57cec5SDimitry Andric .addImm(0); 4460b57cec5SDimitry Andric break; 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric case SystemZ::CLIBCall: 4490b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLIB) 4500b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4510b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 4520b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 453e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 4540b57cec5SDimitry Andric .addImm(0); 4550b57cec5SDimitry Andric break; 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric case SystemZ::CLGIBCall: 4580b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLGIB) 4590b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4600b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 4610b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 462e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 4630b57cec5SDimitry Andric .addImm(0); 4640b57cec5SDimitry Andric break; 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric case SystemZ::TLS_GDCALL: 4670b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRASL) 4680b57cec5SDimitry Andric .addReg(SystemZ::R14D) 4690b57cec5SDimitry Andric .addExpr(getTLSGetOffset(MF->getContext())) 4700b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD)); 4710b57cec5SDimitry Andric break; 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric case SystemZ::TLS_LDCALL: 4740b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRASL) 4750b57cec5SDimitry Andric .addReg(SystemZ::R14D) 4760b57cec5SDimitry Andric .addExpr(getTLSGetOffset(MF->getContext())) 4770b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM)); 4780b57cec5SDimitry Andric break; 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric case SystemZ::GOT: 4810b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::LARL) 4820b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4830b57cec5SDimitry Andric .addExpr(getGlobalOffsetTable(MF->getContext())); 4840b57cec5SDimitry Andric break; 4850b57cec5SDimitry Andric 4860b57cec5SDimitry Andric case SystemZ::IILF64: 4870b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::IILF) 4880b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 4890b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()); 4900b57cec5SDimitry Andric break; 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric case SystemZ::IIHF64: 4930b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::IIHF) 4940b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 4950b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()); 4960b57cec5SDimitry Andric break; 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric case SystemZ::RISBHH: 4990b57cec5SDimitry Andric case SystemZ::RISBHL: 5000b57cec5SDimitry Andric LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG); 5010b57cec5SDimitry Andric break; 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric case SystemZ::RISBLH: 5040b57cec5SDimitry Andric case SystemZ::RISBLL: 5050b57cec5SDimitry Andric LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG); 5060b57cec5SDimitry Andric break; 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric case SystemZ::VLVGP32: 5090b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::VLVGP) 5100b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 5110b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg())) 5120b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())); 5130b57cec5SDimitry Andric break; 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric case SystemZ::VLR32: 5160b57cec5SDimitry Andric case SystemZ::VLR64: 5170b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::VLR) 5180b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 5190b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())); 5200b57cec5SDimitry Andric break; 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric case SystemZ::VL: 5230b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 5240b57cec5SDimitry Andric lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign); 5250b57cec5SDimitry Andric break; 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric case SystemZ::VST: 5280b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 5290b57cec5SDimitry Andric lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign); 5300b57cec5SDimitry Andric break; 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andric case SystemZ::VLM: 5330b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 5340b57cec5SDimitry Andric lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign); 5350b57cec5SDimitry Andric break; 5360b57cec5SDimitry Andric 5370b57cec5SDimitry Andric case SystemZ::VSTM: 5380b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 5390b57cec5SDimitry Andric lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign); 5400b57cec5SDimitry Andric break; 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric case SystemZ::VL32: 5430b57cec5SDimitry Andric LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF); 5440b57cec5SDimitry Andric break; 5450b57cec5SDimitry Andric 5460b57cec5SDimitry Andric case SystemZ::VL64: 5470b57cec5SDimitry Andric LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG); 5480b57cec5SDimitry Andric break; 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric case SystemZ::VST32: 5510b57cec5SDimitry Andric LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF); 5520b57cec5SDimitry Andric break; 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric case SystemZ::VST64: 5550b57cec5SDimitry Andric LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG); 5560b57cec5SDimitry Andric break; 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric case SystemZ::LFER: 5590b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::VLGVF) 5600b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg())) 5610b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())) 5620b57cec5SDimitry Andric .addReg(0).addImm(0); 5630b57cec5SDimitry Andric break; 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric case SystemZ::LEFR: 5660b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::VLVGF) 5670b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 5680b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 5690b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 5700b57cec5SDimitry Andric .addReg(0).addImm(0); 5710b57cec5SDimitry Andric break; 5720b57cec5SDimitry Andric 5730b57cec5SDimitry Andric #define LOWER_LOW(NAME) \ 5740b57cec5SDimitry Andric case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric LOWER_LOW(IILL); 5770b57cec5SDimitry Andric LOWER_LOW(IILH); 5780b57cec5SDimitry Andric LOWER_LOW(TMLL); 5790b57cec5SDimitry Andric LOWER_LOW(TMLH); 5800b57cec5SDimitry Andric LOWER_LOW(NILL); 5810b57cec5SDimitry Andric LOWER_LOW(NILH); 5820b57cec5SDimitry Andric LOWER_LOW(NILF); 5830b57cec5SDimitry Andric LOWER_LOW(OILL); 5840b57cec5SDimitry Andric LOWER_LOW(OILH); 5850b57cec5SDimitry Andric LOWER_LOW(OILF); 5860b57cec5SDimitry Andric LOWER_LOW(XILF); 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric #undef LOWER_LOW 5890b57cec5SDimitry Andric 5900b57cec5SDimitry Andric #define LOWER_HIGH(NAME) \ 5910b57cec5SDimitry Andric case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric LOWER_HIGH(IIHL); 5940b57cec5SDimitry Andric LOWER_HIGH(IIHH); 5950b57cec5SDimitry Andric LOWER_HIGH(TMHL); 5960b57cec5SDimitry Andric LOWER_HIGH(TMHH); 5970b57cec5SDimitry Andric LOWER_HIGH(NIHL); 5980b57cec5SDimitry Andric LOWER_HIGH(NIHH); 5990b57cec5SDimitry Andric LOWER_HIGH(NIHF); 6000b57cec5SDimitry Andric LOWER_HIGH(OIHL); 6010b57cec5SDimitry Andric LOWER_HIGH(OIHH); 6020b57cec5SDimitry Andric LOWER_HIGH(OIHF); 6030b57cec5SDimitry Andric LOWER_HIGH(XIHF); 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric #undef LOWER_HIGH 6060b57cec5SDimitry Andric 6070b57cec5SDimitry Andric case SystemZ::Serialize: 6080b57cec5SDimitry Andric if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization()) 6090b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BCRAsm) 6100b57cec5SDimitry Andric .addImm(14).addReg(SystemZ::R0D); 6110b57cec5SDimitry Andric else 6120b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BCRAsm) 6130b57cec5SDimitry Andric .addImm(15).addReg(SystemZ::R0D); 6140b57cec5SDimitry Andric break; 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric // We want to emit "j .+2" for traps, jumping to the relative immediate field 6170b57cec5SDimitry Andric // of the jump instruction, which is an illegal instruction. We cannot emit a 6180b57cec5SDimitry Andric // "." symbol, so create and emit a temp label before the instruction and use 6190b57cec5SDimitry Andric // that instead. 6200b57cec5SDimitry Andric case SystemZ::Trap: { 6210b57cec5SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 6225ffd83dbSDimitry Andric OutStreamer->emitLabel(DotSym); 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 6250b57cec5SDimitry Andric const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 6260b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::J) 6270b57cec5SDimitry Andric .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 6280b57cec5SDimitry Andric } 6290b57cec5SDimitry Andric break; 6300b57cec5SDimitry Andric 6310b57cec5SDimitry Andric // Conditional traps will create a branch on condition instruction that jumps 6320b57cec5SDimitry Andric // to the relative immediate field of the jump instruction. (eg. "jo .+2") 6330b57cec5SDimitry Andric case SystemZ::CondTrap: { 6340b57cec5SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 6355ffd83dbSDimitry Andric OutStreamer->emitLabel(DotSym); 6360b57cec5SDimitry Andric 6370b57cec5SDimitry Andric const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 6380b57cec5SDimitry Andric const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 6390b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRC) 6400b57cec5SDimitry Andric .addImm(MI->getOperand(0).getImm()) 6410b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 6420b57cec5SDimitry Andric .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 6430b57cec5SDimitry Andric } 6440b57cec5SDimitry Andric break; 6450b57cec5SDimitry Andric 6468bcb0991SDimitry Andric case TargetOpcode::FENTRY_CALL: 6478bcb0991SDimitry Andric LowerFENTRY_CALL(*MI, Lower); 6488bcb0991SDimitry Andric return; 6498bcb0991SDimitry Andric 6500b57cec5SDimitry Andric case TargetOpcode::STACKMAP: 6510b57cec5SDimitry Andric LowerSTACKMAP(*MI); 6520b57cec5SDimitry Andric return; 6530b57cec5SDimitry Andric 6540b57cec5SDimitry Andric case TargetOpcode::PATCHPOINT: 6550b57cec5SDimitry Andric LowerPATCHPOINT(*MI, Lower); 6560b57cec5SDimitry Andric return; 6570b57cec5SDimitry Andric 658fe6060f1SDimitry Andric case SystemZ::EXRL_Pseudo: { 659fe6060f1SDimitry Andric unsigned TargetInsOpc = MI->getOperand(0).getImm(); 660fe6060f1SDimitry Andric Register LenMinus1Reg = MI->getOperand(1).getReg(); 661fe6060f1SDimitry Andric Register DestReg = MI->getOperand(2).getReg(); 662fe6060f1SDimitry Andric int64_t DestDisp = MI->getOperand(3).getImm(); 663fe6060f1SDimitry Andric Register SrcReg = MI->getOperand(4).getReg(); 664fe6060f1SDimitry Andric int64_t SrcDisp = MI->getOperand(5).getImm(); 665fe6060f1SDimitry Andric 666349cc55cSDimitry Andric SystemZTargetStreamer *TS = getTargetStreamer(); 667fe6060f1SDimitry Andric MCSymbol *DotSym = nullptr; 668fe6060f1SDimitry Andric MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg) 669fe6060f1SDimitry Andric .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp); 670349cc55cSDimitry Andric SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget()); 671349cc55cSDimitry Andric SystemZTargetStreamer::EXRLT2SymMap::iterator I = 672349cc55cSDimitry Andric TS->EXRLTargets2Sym.find(ET_STI); 673349cc55cSDimitry Andric if (I != TS->EXRLTargets2Sym.end()) 674fe6060f1SDimitry Andric DotSym = I->second; 675fe6060f1SDimitry Andric else 676349cc55cSDimitry Andric TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol(); 677fe6060f1SDimitry Andric const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); 678fe6060f1SDimitry Andric EmitToStreamer( 679fe6060f1SDimitry Andric *OutStreamer, 680fe6060f1SDimitry Andric MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot)); 681fe6060f1SDimitry Andric return; 682fe6060f1SDimitry Andric } 683fe6060f1SDimitry Andric 6840b57cec5SDimitry Andric default: 6850b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 6860b57cec5SDimitry Andric break; 6870b57cec5SDimitry Andric } 6880b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, LoweredMI); 6890b57cec5SDimitry Andric } 6900b57cec5SDimitry Andric 6910b57cec5SDimitry Andric // Emit the largest nop instruction smaller than or equal to NumBytes 6920b57cec5SDimitry Andric // bytes. Return the size of nop emitted. 6930b57cec5SDimitry Andric static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer, 6940b57cec5SDimitry Andric unsigned NumBytes, const MCSubtargetInfo &STI) { 6950b57cec5SDimitry Andric if (NumBytes < 2) { 6960b57cec5SDimitry Andric llvm_unreachable("Zero nops?"); 6970b57cec5SDimitry Andric return 0; 6980b57cec5SDimitry Andric } 6990b57cec5SDimitry Andric else if (NumBytes < 4) { 7005ffd83dbSDimitry Andric OutStreamer.emitInstruction( 7015ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI); 7020b57cec5SDimitry Andric return 2; 7030b57cec5SDimitry Andric } 7040b57cec5SDimitry Andric else if (NumBytes < 6) { 7055ffd83dbSDimitry Andric OutStreamer.emitInstruction( 7065ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0), 7070b57cec5SDimitry Andric STI); 7080b57cec5SDimitry Andric return 4; 7090b57cec5SDimitry Andric } 7100b57cec5SDimitry Andric else { 7110b57cec5SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 7120b57cec5SDimitry Andric const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); 7135ffd83dbSDimitry Andric OutStreamer.emitLabel(DotSym); 7145ffd83dbSDimitry Andric OutStreamer.emitInstruction( 7155ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI); 7160b57cec5SDimitry Andric return 6; 7170b57cec5SDimitry Andric } 7180b57cec5SDimitry Andric } 7190b57cec5SDimitry Andric 7208bcb0991SDimitry Andric void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI, 7218bcb0991SDimitry Andric SystemZMCInstLower &Lower) { 7228bcb0991SDimitry Andric MCContext &Ctx = MF->getContext(); 723480093f4SDimitry Andric if (MF->getFunction().hasFnAttribute("mrecord-mcount")) { 724480093f4SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 72581ad6265SDimitry Andric OutStreamer->pushSection(); 72681ad6265SDimitry Andric OutStreamer->switchSection( 727480093f4SDimitry Andric Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC)); 7285ffd83dbSDimitry Andric OutStreamer->emitSymbolValue(DotSym, 8); 72981ad6265SDimitry Andric OutStreamer->popSection(); 7305ffd83dbSDimitry Andric OutStreamer->emitLabel(DotSym); 731480093f4SDimitry Andric } 732480093f4SDimitry Andric 733480093f4SDimitry Andric if (MF->getFunction().hasFnAttribute("mnop-mcount")) { 7348bcb0991SDimitry Andric EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo()); 7358bcb0991SDimitry Andric return; 7368bcb0991SDimitry Andric } 7378bcb0991SDimitry Andric 7388bcb0991SDimitry Andric MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__"); 7398bcb0991SDimitry Andric const MCSymbolRefExpr *Op = 7408bcb0991SDimitry Andric MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx); 7415ffd83dbSDimitry Andric OutStreamer->emitInstruction( 7425ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op), 7435ffd83dbSDimitry Andric getSubtargetInfo()); 7448bcb0991SDimitry Andric } 7458bcb0991SDimitry Andric 7460b57cec5SDimitry Andric void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) { 74781ad6265SDimitry Andric auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo(); 7480b57cec5SDimitry Andric 7490b57cec5SDimitry Andric unsigned NumNOPBytes = MI.getOperand(1).getImm(); 7500b57cec5SDimitry Andric 751480093f4SDimitry Andric auto &Ctx = OutStreamer->getContext(); 752480093f4SDimitry Andric MCSymbol *MILabel = Ctx.createTempSymbol(); 7535ffd83dbSDimitry Andric OutStreamer->emitLabel(MILabel); 754480093f4SDimitry Andric 755480093f4SDimitry Andric SM.recordStackMap(*MILabel, MI); 7560b57cec5SDimitry Andric assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!"); 7570b57cec5SDimitry Andric 7580b57cec5SDimitry Andric // Scan ahead to trim the shadow. 7590b57cec5SDimitry Andric unsigned ShadowBytes = 0; 7600b57cec5SDimitry Andric const MachineBasicBlock &MBB = *MI.getParent(); 7610b57cec5SDimitry Andric MachineBasicBlock::const_iterator MII(MI); 7620b57cec5SDimitry Andric ++MII; 7630b57cec5SDimitry Andric while (ShadowBytes < NumNOPBytes) { 7640b57cec5SDimitry Andric if (MII == MBB.end() || 7650b57cec5SDimitry Andric MII->getOpcode() == TargetOpcode::PATCHPOINT || 7660b57cec5SDimitry Andric MII->getOpcode() == TargetOpcode::STACKMAP) 7670b57cec5SDimitry Andric break; 7680b57cec5SDimitry Andric ShadowBytes += TII->getInstSizeInBytes(*MII); 7690b57cec5SDimitry Andric if (MII->isCall()) 7700b57cec5SDimitry Andric break; 7710b57cec5SDimitry Andric ++MII; 7720b57cec5SDimitry Andric } 7730b57cec5SDimitry Andric 7740b57cec5SDimitry Andric // Emit nops. 7750b57cec5SDimitry Andric while (ShadowBytes < NumNOPBytes) 7760b57cec5SDimitry Andric ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes, 7770b57cec5SDimitry Andric getSubtargetInfo()); 7780b57cec5SDimitry Andric } 7790b57cec5SDimitry Andric 7800b57cec5SDimitry Andric // Lower a patchpoint of the form: 7810b57cec5SDimitry Andric // [<def>], <id>, <numBytes>, <target>, <numArgs> 7820b57cec5SDimitry Andric void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI, 7830b57cec5SDimitry Andric SystemZMCInstLower &Lower) { 784480093f4SDimitry Andric auto &Ctx = OutStreamer->getContext(); 785480093f4SDimitry Andric MCSymbol *MILabel = Ctx.createTempSymbol(); 7865ffd83dbSDimitry Andric OutStreamer->emitLabel(MILabel); 787480093f4SDimitry Andric 788480093f4SDimitry Andric SM.recordPatchPoint(*MILabel, MI); 7890b57cec5SDimitry Andric PatchPointOpers Opers(&MI); 7900b57cec5SDimitry Andric 7910b57cec5SDimitry Andric unsigned EncodedBytes = 0; 7920b57cec5SDimitry Andric const MachineOperand &CalleeMO = Opers.getCallTarget(); 7930b57cec5SDimitry Andric 7940b57cec5SDimitry Andric if (CalleeMO.isImm()) { 7950b57cec5SDimitry Andric uint64_t CallTarget = CalleeMO.getImm(); 7960b57cec5SDimitry Andric if (CallTarget) { 7970b57cec5SDimitry Andric unsigned ScratchIdx = -1; 7980b57cec5SDimitry Andric unsigned ScratchReg = 0; 7990b57cec5SDimitry Andric do { 8000b57cec5SDimitry Andric ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1); 8010b57cec5SDimitry Andric ScratchReg = MI.getOperand(ScratchIdx).getReg(); 8020b57cec5SDimitry Andric } while (ScratchReg == SystemZ::R0D); 8030b57cec5SDimitry Andric 8040b57cec5SDimitry Andric // Materialize the call target address 8050b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF) 8060b57cec5SDimitry Andric .addReg(ScratchReg) 8070b57cec5SDimitry Andric .addImm(CallTarget & 0xFFFFFFFF)); 8080b57cec5SDimitry Andric EncodedBytes += 6; 8090b57cec5SDimitry Andric if (CallTarget >> 32) { 8100b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF) 8110b57cec5SDimitry Andric .addReg(ScratchReg) 8120b57cec5SDimitry Andric .addImm(CallTarget >> 32)); 8130b57cec5SDimitry Andric EncodedBytes += 6; 8140b57cec5SDimitry Andric } 8150b57cec5SDimitry Andric 8160b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 8170b57cec5SDimitry Andric .addReg(SystemZ::R14D) 8180b57cec5SDimitry Andric .addReg(ScratchReg)); 8190b57cec5SDimitry Andric EncodedBytes += 2; 8200b57cec5SDimitry Andric } 8210b57cec5SDimitry Andric } else if (CalleeMO.isGlobal()) { 8220b57cec5SDimitry Andric const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT); 8230b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL) 8240b57cec5SDimitry Andric .addReg(SystemZ::R14D) 8250b57cec5SDimitry Andric .addExpr(Expr)); 8260b57cec5SDimitry Andric EncodedBytes += 6; 8270b57cec5SDimitry Andric } 8280b57cec5SDimitry Andric 8290b57cec5SDimitry Andric // Emit padding. 8300b57cec5SDimitry Andric unsigned NumBytes = Opers.getNumPatchBytes(); 8310b57cec5SDimitry Andric assert(NumBytes >= EncodedBytes && 8320b57cec5SDimitry Andric "Patchpoint can't request size less than the length of a call."); 8330b57cec5SDimitry Andric assert((NumBytes - EncodedBytes) % 2 == 0 && 8340b57cec5SDimitry Andric "Invalid number of NOP bytes requested!"); 8350b57cec5SDimitry Andric while (EncodedBytes < NumBytes) 8360b57cec5SDimitry Andric EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes, 8370b57cec5SDimitry Andric getSubtargetInfo()); 8380b57cec5SDimitry Andric } 8390b57cec5SDimitry Andric 840bdd1243dSDimitry Andric // The *alignment* of 128-bit vector types is different between the software 841bdd1243dSDimitry Andric // and hardware vector ABIs. If the there is an externally visible use of a 842bdd1243dSDimitry Andric // vector type in the module it should be annotated with an attribute. 843bdd1243dSDimitry Andric void SystemZAsmPrinter::emitAttributes(Module &M) { 844bdd1243dSDimitry Andric if (M.getModuleFlag("s390x-visible-vector-ABI")) { 845bdd1243dSDimitry Andric bool HasVectorFeature = 846*06c3fb27SDimitry Andric TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureVector); 847bdd1243dSDimitry Andric OutStreamer->emitGNUAttribute(8, HasVectorFeature ? 2 : 1); 848bdd1243dSDimitry Andric } 849bdd1243dSDimitry Andric } 850bdd1243dSDimitry Andric 8510b57cec5SDimitry Andric // Convert a SystemZ-specific constant pool modifier into the associated 8520b57cec5SDimitry Andric // MCSymbolRefExpr variant kind. 8530b57cec5SDimitry Andric static MCSymbolRefExpr::VariantKind 8540b57cec5SDimitry Andric getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) { 8550b57cec5SDimitry Andric switch (Modifier) { 8560b57cec5SDimitry Andric case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD; 8570b57cec5SDimitry Andric case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM; 8580b57cec5SDimitry Andric case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF; 8590b57cec5SDimitry Andric case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF; 8600b57cec5SDimitry Andric } 8610b57cec5SDimitry Andric llvm_unreachable("Invalid SystemCPModifier!"); 8620b57cec5SDimitry Andric } 8630b57cec5SDimitry Andric 8645ffd83dbSDimitry Andric void SystemZAsmPrinter::emitMachineConstantPoolValue( 8655ffd83dbSDimitry Andric MachineConstantPoolValue *MCPV) { 8660b57cec5SDimitry Andric auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV); 8670b57cec5SDimitry Andric 8680b57cec5SDimitry Andric const MCExpr *Expr = 8690b57cec5SDimitry Andric MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()), 8700b57cec5SDimitry Andric getModifierVariantKind(ZCPV->getModifier()), 8710b57cec5SDimitry Andric OutContext); 8720b57cec5SDimitry Andric uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType()); 8730b57cec5SDimitry Andric 8745ffd83dbSDimitry Andric OutStreamer->emitValue(Expr, Size); 8750b57cec5SDimitry Andric } 8760b57cec5SDimitry Andric 877bdd1243dSDimitry Andric static void printFormattedRegName(const MCAsmInfo *MAI, unsigned RegNo, 878bdd1243dSDimitry Andric raw_ostream &OS) { 879bdd1243dSDimitry Andric const char *RegName = SystemZInstPrinter::getRegisterName(RegNo); 880bdd1243dSDimitry Andric if (MAI->getAssemblerDialect() == AD_HLASM) { 881bdd1243dSDimitry Andric // Skip register prefix so that only register number is left 882bdd1243dSDimitry Andric assert(isalpha(RegName[0]) && isdigit(RegName[1])); 883bdd1243dSDimitry Andric OS << (RegName + 1); 884bdd1243dSDimitry Andric } else 885bdd1243dSDimitry Andric OS << '%' << RegName; 886bdd1243dSDimitry Andric } 887bdd1243dSDimitry Andric 888bdd1243dSDimitry Andric static void printOperand(const MCOperand &MCOp, const MCAsmInfo *MAI, 889bdd1243dSDimitry Andric raw_ostream &OS) { 890bdd1243dSDimitry Andric if (MCOp.isReg()) { 891bdd1243dSDimitry Andric if (!MCOp.getReg()) 892bdd1243dSDimitry Andric OS << '0'; 893bdd1243dSDimitry Andric else 894bdd1243dSDimitry Andric printFormattedRegName(MAI, MCOp.getReg(), OS); 895bdd1243dSDimitry Andric } else if (MCOp.isImm()) 896bdd1243dSDimitry Andric OS << MCOp.getImm(); 897bdd1243dSDimitry Andric else if (MCOp.isExpr()) 898bdd1243dSDimitry Andric MCOp.getExpr()->print(OS, MAI); 899bdd1243dSDimitry Andric else 900bdd1243dSDimitry Andric llvm_unreachable("Invalid operand"); 901bdd1243dSDimitry Andric } 902bdd1243dSDimitry Andric 903bdd1243dSDimitry Andric static void printAddress(const MCAsmInfo *MAI, unsigned Base, 904bdd1243dSDimitry Andric const MCOperand &DispMO, unsigned Index, 905bdd1243dSDimitry Andric raw_ostream &OS) { 906bdd1243dSDimitry Andric printOperand(DispMO, MAI, OS); 907bdd1243dSDimitry Andric if (Base || Index) { 908bdd1243dSDimitry Andric OS << '('; 909bdd1243dSDimitry Andric if (Index) { 910bdd1243dSDimitry Andric printFormattedRegName(MAI, Index, OS); 911bdd1243dSDimitry Andric if (Base) 912bdd1243dSDimitry Andric OS << ','; 913bdd1243dSDimitry Andric } 914bdd1243dSDimitry Andric if (Base) 915bdd1243dSDimitry Andric printFormattedRegName(MAI, Base, OS); 916bdd1243dSDimitry Andric OS << ')'; 917bdd1243dSDimitry Andric } 918bdd1243dSDimitry Andric } 919bdd1243dSDimitry Andric 9200b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 9210b57cec5SDimitry Andric const char *ExtraCode, 9220b57cec5SDimitry Andric raw_ostream &OS) { 923fe6060f1SDimitry Andric const MCRegisterInfo &MRI = *TM.getMCRegisterInfo(); 924fe6060f1SDimitry Andric const MachineOperand &MO = MI->getOperand(OpNo); 925fe6060f1SDimitry Andric MCOperand MCOp; 926fe6060f1SDimitry Andric if (ExtraCode) { 927fe6060f1SDimitry Andric if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() && 928fe6060f1SDimitry Andric SystemZ::GR128BitRegClass.contains(MO.getReg())) 929fe6060f1SDimitry Andric MCOp = 930fe6060f1SDimitry Andric MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64)); 931fe6060f1SDimitry Andric else 9320b57cec5SDimitry Andric return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS); 933fe6060f1SDimitry Andric } else { 9340b57cec5SDimitry Andric SystemZMCInstLower Lower(MF->getContext(), *this); 935fe6060f1SDimitry Andric MCOp = Lower.lowerOperand(MO); 936fe6060f1SDimitry Andric } 937bdd1243dSDimitry Andric printOperand(MCOp, MAI, OS); 9380b57cec5SDimitry Andric return false; 9390b57cec5SDimitry Andric } 9400b57cec5SDimitry Andric 9410b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 9420b57cec5SDimitry Andric unsigned OpNo, 9430b57cec5SDimitry Andric const char *ExtraCode, 9440b57cec5SDimitry Andric raw_ostream &OS) { 945349cc55cSDimitry Andric printAddress(MAI, MI->getOperand(OpNo).getReg(), 946349cc55cSDimitry Andric MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()), 9470b57cec5SDimitry Andric MI->getOperand(OpNo + 2).getReg(), OS); 9480b57cec5SDimitry Andric return false; 9490b57cec5SDimitry Andric } 9500b57cec5SDimitry Andric 9515ffd83dbSDimitry Andric void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) { 952*06c3fb27SDimitry Andric auto TT = OutContext.getTargetTriple(); 953*06c3fb27SDimitry Andric if (TT.isOSzOS()) { 954*06c3fb27SDimitry Andric emitADASection(); 955*06c3fb27SDimitry Andric } 956bdd1243dSDimitry Andric emitAttributes(M); 9570b57cec5SDimitry Andric } 9580b57cec5SDimitry Andric 959*06c3fb27SDimitry Andric void SystemZAsmPrinter::emitADASection() { 960*06c3fb27SDimitry Andric OutStreamer->pushSection(); 961*06c3fb27SDimitry Andric 962*06c3fb27SDimitry Andric const unsigned PointerSize = getDataLayout().getPointerSize(); 963*06c3fb27SDimitry Andric OutStreamer->switchSection(getObjFileLowering().getADASection()); 964*06c3fb27SDimitry Andric 965*06c3fb27SDimitry Andric unsigned EmittedBytes = 0; 966*06c3fb27SDimitry Andric for (auto &Entry : ADATable.getTable()) { 967*06c3fb27SDimitry Andric const MCSymbol *Sym; 968*06c3fb27SDimitry Andric unsigned SlotKind; 969*06c3fb27SDimitry Andric std::tie(Sym, SlotKind) = Entry.first; 970*06c3fb27SDimitry Andric unsigned Offset = Entry.second; 971*06c3fb27SDimitry Andric assert(Offset == EmittedBytes && "Offset not as expected"); 972*06c3fb27SDimitry Andric (void)EmittedBytes; 973*06c3fb27SDimitry Andric #define EMIT_COMMENT(Str) \ 974*06c3fb27SDimitry Andric OutStreamer->AddComment(Twine("Offset ") \ 975*06c3fb27SDimitry Andric .concat(utostr(Offset)) \ 976*06c3fb27SDimitry Andric .concat(" " Str " ") \ 977*06c3fb27SDimitry Andric .concat(Sym->getName())); 978*06c3fb27SDimitry Andric switch (SlotKind) { 979*06c3fb27SDimitry Andric case SystemZII::MO_ADA_DIRECT_FUNC_DESC: 980*06c3fb27SDimitry Andric // Language Environment DLL logic requires function descriptors, for 981*06c3fb27SDimitry Andric // imported functions, that are placed in the ADA to be 8 byte aligned. 982*06c3fb27SDimitry Andric EMIT_COMMENT("function descriptor of"); 983*06c3fb27SDimitry Andric OutStreamer->emitValue( 984*06c3fb27SDimitry Andric SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_RCon, 985*06c3fb27SDimitry Andric MCSymbolRefExpr::create(Sym, OutContext), 986*06c3fb27SDimitry Andric OutContext), 987*06c3fb27SDimitry Andric PointerSize); 988*06c3fb27SDimitry Andric OutStreamer->emitValue( 989*06c3fb27SDimitry Andric SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_VCon, 990*06c3fb27SDimitry Andric MCSymbolRefExpr::create(Sym, OutContext), 991*06c3fb27SDimitry Andric OutContext), 992*06c3fb27SDimitry Andric PointerSize); 993*06c3fb27SDimitry Andric EmittedBytes += PointerSize * 2; 994*06c3fb27SDimitry Andric break; 995*06c3fb27SDimitry Andric case SystemZII::MO_ADA_DATA_SYMBOL_ADDR: 996*06c3fb27SDimitry Andric EMIT_COMMENT("pointer to data symbol"); 997*06c3fb27SDimitry Andric OutStreamer->emitValue( 998*06c3fb27SDimitry Andric SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_None, 999*06c3fb27SDimitry Andric MCSymbolRefExpr::create(Sym, OutContext), 1000*06c3fb27SDimitry Andric OutContext), 1001*06c3fb27SDimitry Andric PointerSize); 1002*06c3fb27SDimitry Andric EmittedBytes += PointerSize; 1003*06c3fb27SDimitry Andric break; 1004*06c3fb27SDimitry Andric case SystemZII::MO_ADA_INDIRECT_FUNC_DESC: { 1005*06c3fb27SDimitry Andric MCSymbol *Alias = OutContext.createTempSymbol( 1006*06c3fb27SDimitry Andric Twine(Sym->getName()).concat("@indirect")); 1007*06c3fb27SDimitry Andric OutStreamer->emitAssignment(Alias, 1008*06c3fb27SDimitry Andric MCSymbolRefExpr::create(Sym, OutContext)); 1009*06c3fb27SDimitry Andric OutStreamer->emitSymbolAttribute(Alias, MCSA_IndirectSymbol); 1010*06c3fb27SDimitry Andric 1011*06c3fb27SDimitry Andric EMIT_COMMENT("pointer to function descriptor"); 1012*06c3fb27SDimitry Andric OutStreamer->emitValue( 1013*06c3fb27SDimitry Andric SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_VCon, 1014*06c3fb27SDimitry Andric MCSymbolRefExpr::create(Alias, OutContext), 1015*06c3fb27SDimitry Andric OutContext), 1016*06c3fb27SDimitry Andric PointerSize); 1017*06c3fb27SDimitry Andric EmittedBytes += PointerSize; 1018*06c3fb27SDimitry Andric break; 1019*06c3fb27SDimitry Andric } 1020*06c3fb27SDimitry Andric default: 1021*06c3fb27SDimitry Andric llvm_unreachable("Unexpected slot kind"); 1022*06c3fb27SDimitry Andric } 1023*06c3fb27SDimitry Andric #undef EMIT_COMMENT 1024*06c3fb27SDimitry Andric } 1025*06c3fb27SDimitry Andric OutStreamer->popSection(); 1026*06c3fb27SDimitry Andric } 1027*06c3fb27SDimitry Andric 102881ad6265SDimitry Andric void SystemZAsmPrinter::emitFunctionBodyEnd() { 102981ad6265SDimitry Andric if (TM.getTargetTriple().isOSzOS()) { 103081ad6265SDimitry Andric // Emit symbol for the end of function if the z/OS target streamer 103181ad6265SDimitry Andric // is used. This is needed to calculate the size of the function. 103281ad6265SDimitry Andric MCSymbol *FnEndSym = createTempSymbol("func_end"); 103381ad6265SDimitry Andric OutStreamer->emitLabel(FnEndSym); 103481ad6265SDimitry Andric 103581ad6265SDimitry Andric OutStreamer->pushSection(); 103681ad6265SDimitry Andric OutStreamer->switchSection(getObjFileLowering().getPPA1Section()); 103781ad6265SDimitry Andric emitPPA1(FnEndSym); 103881ad6265SDimitry Andric OutStreamer->popSection(); 103981ad6265SDimitry Andric 104081ad6265SDimitry Andric CurrentFnPPA1Sym = nullptr; 104181ad6265SDimitry Andric CurrentFnEPMarkerSym = nullptr; 104281ad6265SDimitry Andric } 104381ad6265SDimitry Andric } 104481ad6265SDimitry Andric 104581ad6265SDimitry Andric static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg, 104681ad6265SDimitry Andric bool StackProtector, bool FPRMask, bool VRMask) { 104781ad6265SDimitry Andric enum class PPA1Flag1 : uint8_t { 104881ad6265SDimitry Andric DSA64Bit = (0x80 >> 0), 104981ad6265SDimitry Andric VarArg = (0x80 >> 7), 105081ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(DSA64Bit) 105181ad6265SDimitry Andric }; 105281ad6265SDimitry Andric enum class PPA1Flag2 : uint8_t { 105381ad6265SDimitry Andric ExternalProcedure = (0x80 >> 0), 105481ad6265SDimitry Andric STACKPROTECTOR = (0x80 >> 3), 105581ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure) 105681ad6265SDimitry Andric }; 105781ad6265SDimitry Andric enum class PPA1Flag3 : uint8_t { 105881ad6265SDimitry Andric FPRMask = (0x80 >> 2), 105981ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(FPRMask) 106081ad6265SDimitry Andric }; 106181ad6265SDimitry Andric enum class PPA1Flag4 : uint8_t { 106281ad6265SDimitry Andric EPMOffsetPresent = (0x80 >> 0), 106381ad6265SDimitry Andric VRMask = (0x80 >> 2), 106481ad6265SDimitry Andric ProcedureNamePresent = (0x80 >> 7), 106581ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent) 106681ad6265SDimitry Andric }; 106781ad6265SDimitry Andric 106881ad6265SDimitry Andric // Declare optional section flags that can be modified. 106981ad6265SDimitry Andric auto Flags1 = PPA1Flag1(0); 107081ad6265SDimitry Andric auto Flags2 = PPA1Flag2::ExternalProcedure; 107181ad6265SDimitry Andric auto Flags3 = PPA1Flag3(0); 107281ad6265SDimitry Andric auto Flags4 = PPA1Flag4::EPMOffsetPresent | PPA1Flag4::ProcedureNamePresent; 107381ad6265SDimitry Andric 107481ad6265SDimitry Andric Flags1 |= PPA1Flag1::DSA64Bit; 107581ad6265SDimitry Andric 107681ad6265SDimitry Andric if (VarArg) 107781ad6265SDimitry Andric Flags1 |= PPA1Flag1::VarArg; 107881ad6265SDimitry Andric 107981ad6265SDimitry Andric if (StackProtector) 108081ad6265SDimitry Andric Flags2 |= PPA1Flag2::STACKPROTECTOR; 108181ad6265SDimitry Andric 108281ad6265SDimitry Andric // SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in. 108381ad6265SDimitry Andric if (FPRMask) 108481ad6265SDimitry Andric Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag. 108581ad6265SDimitry Andric 108681ad6265SDimitry Andric if (VRMask) 108781ad6265SDimitry Andric Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag. 108881ad6265SDimitry Andric 108981ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 1"); 109081ad6265SDimitry Andric if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit) 109181ad6265SDimitry Andric OutStreamer->AddComment(" Bit 0: 1 = 64-bit DSA"); 109281ad6265SDimitry Andric else 109381ad6265SDimitry Andric OutStreamer->AddComment(" Bit 0: 0 = 32-bit DSA"); 109481ad6265SDimitry Andric if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg) 109581ad6265SDimitry Andric OutStreamer->AddComment(" Bit 7: 1 = Vararg function"); 109681ad6265SDimitry Andric OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1. 109781ad6265SDimitry Andric 109881ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 2"); 109981ad6265SDimitry Andric if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure) 110081ad6265SDimitry Andric OutStreamer->AddComment(" Bit 0: 1 = External procedure"); 110181ad6265SDimitry Andric if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR) 110281ad6265SDimitry Andric OutStreamer->AddComment(" Bit 3: 1 = STACKPROTECT is enabled"); 110381ad6265SDimitry Andric else 110481ad6265SDimitry Andric OutStreamer->AddComment(" Bit 3: 0 = STACKPROTECT is not enabled"); 110581ad6265SDimitry Andric OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2. 110681ad6265SDimitry Andric 110781ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 3"); 110881ad6265SDimitry Andric if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask) 110981ad6265SDimitry Andric OutStreamer->AddComment(" Bit 2: 1 = FP Reg Mask is in optional area"); 111081ad6265SDimitry Andric OutStreamer->emitInt8( 111181ad6265SDimitry Andric static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections). 111281ad6265SDimitry Andric 111381ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 4"); 111481ad6265SDimitry Andric if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask) 111581ad6265SDimitry Andric OutStreamer->AddComment(" Bit 2: 1 = Vector Reg Mask is in optional area"); 111681ad6265SDimitry Andric OutStreamer->emitInt8(static_cast<uint8_t>( 111781ad6265SDimitry Andric Flags4)); // Flags 4 (optional sections, always emit these). 111881ad6265SDimitry Andric } 111981ad6265SDimitry Andric 112081ad6265SDimitry Andric void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) { 112181ad6265SDimitry Andric const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo(); 112281ad6265SDimitry Andric const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 112381ad6265SDimitry Andric const auto TargetHasVector = Subtarget.hasVector(); 112481ad6265SDimitry Andric 112581ad6265SDimitry Andric const SystemZMachineFunctionInfo *ZFI = 112681ad6265SDimitry Andric MF->getInfo<SystemZMachineFunctionInfo>(); 112781ad6265SDimitry Andric const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>( 112881ad6265SDimitry Andric Subtarget.getFrameLowering()); 112981ad6265SDimitry Andric const MachineFrameInfo &MFFrame = MF->getFrameInfo(); 113081ad6265SDimitry Andric 113181ad6265SDimitry Andric // Get saved GPR/FPR/VPR masks. 113281ad6265SDimitry Andric const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo(); 113381ad6265SDimitry Andric uint16_t SavedGPRMask = 0; 113481ad6265SDimitry Andric uint16_t SavedFPRMask = 0; 113581ad6265SDimitry Andric uint8_t SavedVRMask = 0; 113681ad6265SDimitry Andric int64_t OffsetFPR = 0; 113781ad6265SDimitry Andric int64_t OffsetVR = 0; 113881ad6265SDimitry Andric const int64_t TopOfStack = 113981ad6265SDimitry Andric MFFrame.getOffsetAdjustment() + MFFrame.getStackSize(); 114081ad6265SDimitry Andric 114181ad6265SDimitry Andric // Loop over the spilled registers. The CalleeSavedInfo can't be used because 114281ad6265SDimitry Andric // it does not contain all spilled registers. 114381ad6265SDimitry Andric for (unsigned I = ZFI->getSpillGPRRegs().LowGPR, 114481ad6265SDimitry Andric E = ZFI->getSpillGPRRegs().HighGPR; 114581ad6265SDimitry Andric I && E && I <= E; ++I) { 114681ad6265SDimitry Andric unsigned V = TRI->getEncodingValue((Register)I); 114781ad6265SDimitry Andric assert(V < 16 && "GPR index out of range"); 114881ad6265SDimitry Andric SavedGPRMask |= 1 << (15 - V); 114981ad6265SDimitry Andric } 115081ad6265SDimitry Andric 115181ad6265SDimitry Andric for (auto &CS : CSI) { 115281ad6265SDimitry Andric unsigned Reg = CS.getReg(); 115381ad6265SDimitry Andric unsigned I = TRI->getEncodingValue(Reg); 115481ad6265SDimitry Andric 115581ad6265SDimitry Andric if (SystemZ::FP64BitRegClass.contains(Reg)) { 115681ad6265SDimitry Andric assert(I < 16 && "FPR index out of range"); 115781ad6265SDimitry Andric SavedFPRMask |= 1 << (15 - I); 115881ad6265SDimitry Andric int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx()); 115981ad6265SDimitry Andric if (Temp < OffsetFPR) 116081ad6265SDimitry Andric OffsetFPR = Temp; 116181ad6265SDimitry Andric } else if (SystemZ::VR128BitRegClass.contains(Reg)) { 116281ad6265SDimitry Andric assert(I >= 16 && I <= 23 && "VPR index out of range"); 116381ad6265SDimitry Andric unsigned BitNum = I - 16; 116481ad6265SDimitry Andric SavedVRMask |= 1 << (7 - BitNum); 116581ad6265SDimitry Andric int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx()); 116681ad6265SDimitry Andric if (Temp < OffsetVR) 116781ad6265SDimitry Andric OffsetVR = Temp; 116881ad6265SDimitry Andric } 116981ad6265SDimitry Andric } 117081ad6265SDimitry Andric 117181ad6265SDimitry Andric // Adjust the offset. 117281ad6265SDimitry Andric OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0; 117381ad6265SDimitry Andric OffsetVR += (OffsetVR < 0) ? TopOfStack : 0; 117481ad6265SDimitry Andric 117581ad6265SDimitry Andric // Get alloca register. 117681ad6265SDimitry Andric uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF)); 117781ad6265SDimitry Andric uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0; 117881ad6265SDimitry Andric assert(AllocaReg < 16 && "Can't have alloca register larger than 15"); 117981ad6265SDimitry Andric (void)AllocaReg; 118081ad6265SDimitry Andric 118181ad6265SDimitry Andric // Build FPR save area offset. 118281ad6265SDimitry Andric uint32_t FrameAndFPROffset = 0; 118381ad6265SDimitry Andric if (SavedFPRMask) { 118481ad6265SDimitry Andric uint64_t FPRSaveAreaOffset = OffsetFPR; 118581ad6265SDimitry Andric assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range"); 118681ad6265SDimitry Andric 118781ad6265SDimitry Andric FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits. 118881ad6265SDimitry Andric FrameAndFPROffset |= FrameReg << 28; // Put into top 4 bits. 118981ad6265SDimitry Andric } 119081ad6265SDimitry Andric 119181ad6265SDimitry Andric // Build VR save area offset. 119281ad6265SDimitry Andric uint32_t FrameAndVROffset = 0; 119381ad6265SDimitry Andric if (TargetHasVector && SavedVRMask) { 119481ad6265SDimitry Andric uint64_t VRSaveAreaOffset = OffsetVR; 119581ad6265SDimitry Andric assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range"); 119681ad6265SDimitry Andric 119781ad6265SDimitry Andric FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits. 119881ad6265SDimitry Andric FrameAndVROffset |= FrameReg << 28; // Put into top 4 bits. 119981ad6265SDimitry Andric } 120081ad6265SDimitry Andric 120181ad6265SDimitry Andric // Emit PPA1 section. 120281ad6265SDimitry Andric OutStreamer->AddComment("PPA1"); 120381ad6265SDimitry Andric OutStreamer->emitLabel(CurrentFnPPA1Sym); 120481ad6265SDimitry Andric OutStreamer->AddComment("Version"); 120581ad6265SDimitry Andric OutStreamer->emitInt8(0x02); // Version. 120681ad6265SDimitry Andric OutStreamer->AddComment("LE Signature X'CE'"); 120781ad6265SDimitry Andric OutStreamer->emitInt8(0xCE); // CEL signature. 120881ad6265SDimitry Andric OutStreamer->AddComment("Saved GPR Mask"); 120981ad6265SDimitry Andric OutStreamer->emitInt16(SavedGPRMask); 121081ad6265SDimitry Andric 121181ad6265SDimitry Andric emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(), 121281ad6265SDimitry Andric MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0, 121381ad6265SDimitry Andric TargetHasVector && SavedVRMask != 0); 121481ad6265SDimitry Andric 121581ad6265SDimitry Andric OutStreamer->AddComment("Length/4 of Parms"); 121681ad6265SDimitry Andric OutStreamer->emitInt16( 1217*06c3fb27SDimitry Andric static_cast<uint16_t>(ZFI->getSizeOfFnParams() / 4)); // Parms/4. 121881ad6265SDimitry Andric OutStreamer->AddComment("Length of Code"); 121981ad6265SDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4); 122081ad6265SDimitry Andric 122181ad6265SDimitry Andric // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3). 122281ad6265SDimitry Andric if (SavedFPRMask) { 122381ad6265SDimitry Andric OutStreamer->AddComment("FPR mask"); 122481ad6265SDimitry Andric OutStreamer->emitInt16(SavedFPRMask); 122581ad6265SDimitry Andric OutStreamer->AddComment("AR mask"); 122681ad6265SDimitry Andric OutStreamer->emitInt16(0); // AR Mask, unused currently. 122781ad6265SDimitry Andric OutStreamer->AddComment("FPR Save Area Locator"); 122881ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 0-3: Register R") 122981ad6265SDimitry Andric .concat(utostr(FrameAndFPROffset >> 28)) 123081ad6265SDimitry Andric .str()); 123181ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 4-31: Offset ") 123281ad6265SDimitry Andric .concat(utostr(FrameAndFPROffset & 0x0FFFFFFF)) 123381ad6265SDimitry Andric .str()); 123481ad6265SDimitry Andric OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with 123581ad6265SDimitry Andric // register to add value to 123681ad6265SDimitry Andric // (alloca reg). 123781ad6265SDimitry Andric } 123881ad6265SDimitry Andric 123981ad6265SDimitry Andric // Emit saved VR mask to VR save area. 124081ad6265SDimitry Andric if (TargetHasVector && SavedVRMask) { 124181ad6265SDimitry Andric OutStreamer->AddComment("VR mask"); 124281ad6265SDimitry Andric OutStreamer->emitInt8(SavedVRMask); 124381ad6265SDimitry Andric OutStreamer->emitInt8(0); // Reserved. 124481ad6265SDimitry Andric OutStreamer->emitInt16(0); // Also reserved. 124581ad6265SDimitry Andric OutStreamer->AddComment("VR Save Area Locator"); 124681ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 0-3: Register R") 124781ad6265SDimitry Andric .concat(utostr(FrameAndVROffset >> 28)) 124881ad6265SDimitry Andric .str()); 124981ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 4-31: Offset ") 125081ad6265SDimitry Andric .concat(utostr(FrameAndVROffset & 0x0FFFFFFF)) 125181ad6265SDimitry Andric .str()); 125281ad6265SDimitry Andric OutStreamer->emitInt32(FrameAndVROffset); 125381ad6265SDimitry Andric } 125481ad6265SDimitry Andric 125581ad6265SDimitry Andric // Emit offset to entry point optional section (0x80 of flags 4). 125681ad6265SDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym, 125781ad6265SDimitry Andric 4); 125881ad6265SDimitry Andric } 125981ad6265SDimitry Andric 126004eeddc0SDimitry Andric void SystemZAsmPrinter::emitFunctionEntryLabel() { 126181ad6265SDimitry Andric const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 126204eeddc0SDimitry Andric 126304eeddc0SDimitry Andric if (Subtarget.getTargetTriple().isOSzOS()) { 126404eeddc0SDimitry Andric MCContext &OutContext = OutStreamer->getContext(); 126581ad6265SDimitry Andric 126681ad6265SDimitry Andric // Save information for later use. 126781ad6265SDimitry Andric std::string N(MF->getFunction().hasName() 126881ad6265SDimitry Andric ? Twine(MF->getFunction().getName()).concat("_").str() 126981ad6265SDimitry Andric : ""); 127081ad6265SDimitry Andric 127181ad6265SDimitry Andric CurrentFnEPMarkerSym = 127281ad6265SDimitry Andric OutContext.createTempSymbol(Twine("EPM_").concat(N).str(), true); 127381ad6265SDimitry Andric CurrentFnPPA1Sym = 127481ad6265SDimitry Andric OutContext.createTempSymbol(Twine("PPA1_").concat(N).str(), true); 127504eeddc0SDimitry Andric 127604eeddc0SDimitry Andric // EntryPoint Marker 127704eeddc0SDimitry Andric const MachineFrameInfo &MFFrame = MF->getFrameInfo(); 127804eeddc0SDimitry Andric bool IsUsingAlloca = MFFrame.hasVarSizedObjects(); 127904eeddc0SDimitry Andric 128004eeddc0SDimitry Andric // Set Flags 128104eeddc0SDimitry Andric uint8_t Flags = 0; 128204eeddc0SDimitry Andric if (IsUsingAlloca) 128304eeddc0SDimitry Andric Flags |= 0x04; 128404eeddc0SDimitry Andric 128504eeddc0SDimitry Andric uint32_t DSASize = MFFrame.getStackSize(); 128604eeddc0SDimitry Andric 128704eeddc0SDimitry Andric // Combine into top 27 bits of DSASize and bottom 5 bits of Flags. 128804eeddc0SDimitry Andric uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5 128904eeddc0SDimitry Andric DSAAndFlags |= Flags; 129004eeddc0SDimitry Andric 129104eeddc0SDimitry Andric // Emit entry point marker section. 129204eeddc0SDimitry Andric OutStreamer->AddComment("XPLINK Routine Layout Entry"); 129381ad6265SDimitry Andric OutStreamer->emitLabel(CurrentFnEPMarkerSym); 129404eeddc0SDimitry Andric OutStreamer->AddComment("Eyecatcher 0x00C300C500C500"); 129504eeddc0SDimitry Andric OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher. 129604eeddc0SDimitry Andric OutStreamer->AddComment("Mark Type C'1'"); 129704eeddc0SDimitry Andric OutStreamer->emitInt8(0xF1); // Mark Type. 129881ad6265SDimitry Andric OutStreamer->AddComment("Offset to PPA1"); 129981ad6265SDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(CurrentFnPPA1Sym, CurrentFnEPMarkerSym, 130081ad6265SDimitry Andric 4); 130104eeddc0SDimitry Andric if (OutStreamer->isVerboseAsm()) { 130204eeddc0SDimitry Andric OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize)); 130304eeddc0SDimitry Andric OutStreamer->AddComment("Entry Flags"); 130404eeddc0SDimitry Andric if (Flags & 0x04) 130504eeddc0SDimitry Andric OutStreamer->AddComment(" Bit 2: 1 = Uses alloca"); 130604eeddc0SDimitry Andric else 130704eeddc0SDimitry Andric OutStreamer->AddComment(" Bit 2: 0 = Does not use alloca"); 130804eeddc0SDimitry Andric } 130904eeddc0SDimitry Andric OutStreamer->emitInt32(DSAAndFlags); 131004eeddc0SDimitry Andric } 131104eeddc0SDimitry Andric 131204eeddc0SDimitry Andric AsmPrinter::emitFunctionEntryLabel(); 131304eeddc0SDimitry Andric } 131404eeddc0SDimitry Andric 13150b57cec5SDimitry Andric // Force static initialization. 1316480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() { 13170b57cec5SDimitry Andric RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget()); 13180b57cec5SDimitry Andric } 1319