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