xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
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"
27*349cc55cSDimitry 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) {
910b57cec5SDimitry Andric   if (!MI->hasOneMemOperand())
920b57cec5SDimitry Andric     return;
930b57cec5SDimitry Andric   const MachineMemOperand *MMO = *MI->memoperands_begin();
940b57cec5SDimitry Andric   unsigned AlignmentHint = 0;
955ffd83dbSDimitry Andric   if (MMO->getAlign() >= Align(16))
960b57cec5SDimitry Andric     AlignmentHint = 4;
975ffd83dbSDimitry Andric   else if (MMO->getAlign() >= Align(8))
980b57cec5SDimitry Andric     AlignmentHint = 3;
990b57cec5SDimitry Andric   if (AlignmentHint == 0)
1000b57cec5SDimitry Andric     return;
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   LoweredMI.setOpcode(Opcode);
1030b57cec5SDimitry Andric   LoweredMI.addOperand(MCOperand::createImm(AlignmentHint));
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric // MI loads the high part of a vector from memory.  Return an instruction
1070b57cec5SDimitry Andric // that uses replicating vector load Opcode to do the same thing.
1080b57cec5SDimitry Andric static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) {
1090b57cec5SDimitry Andric   return MCInstBuilder(Opcode)
1100b57cec5SDimitry Andric     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
1110b57cec5SDimitry Andric     .addReg(MI->getOperand(1).getReg())
1120b57cec5SDimitry Andric     .addImm(MI->getOperand(2).getImm())
1130b57cec5SDimitry Andric     .addReg(MI->getOperand(3).getReg());
1140b57cec5SDimitry Andric }
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric // MI stores the high part of a vector to memory.  Return an instruction
1170b57cec5SDimitry Andric // that uses elemental vector store Opcode to do the same thing.
1180b57cec5SDimitry Andric static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {
1190b57cec5SDimitry Andric   return MCInstBuilder(Opcode)
1200b57cec5SDimitry Andric     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
1210b57cec5SDimitry Andric     .addReg(MI->getOperand(1).getReg())
1220b57cec5SDimitry Andric     .addImm(MI->getOperand(2).getImm())
1230b57cec5SDimitry Andric     .addReg(MI->getOperand(3).getReg())
1240b57cec5SDimitry Andric     .addImm(0);
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric 
1275ffd83dbSDimitry Andric void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
1280b57cec5SDimitry Andric   SystemZMCInstLower Lower(MF->getContext(), *this);
129fe6060f1SDimitry Andric   const SystemZSubtarget *Subtarget = &MF->getSubtarget<SystemZSubtarget>();
1300b57cec5SDimitry Andric   MCInst LoweredMI;
1310b57cec5SDimitry Andric   switch (MI->getOpcode()) {
1320b57cec5SDimitry Andric   case SystemZ::Return:
133fe6060f1SDimitry Andric     if (Subtarget->isTargetXPLINK64())
134fe6060f1SDimitry Andric       LoweredMI =
135fe6060f1SDimitry Andric           MCInstBuilder(SystemZ::B).addReg(SystemZ::R7D).addImm(2).addReg(0);
136fe6060f1SDimitry Andric     else
1370b57cec5SDimitry Andric       LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D);
1380b57cec5SDimitry Andric     break;
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   case SystemZ::CondReturn:
1410b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BCR)
1420b57cec5SDimitry Andric       .addImm(MI->getOperand(0).getImm())
1430b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
1440b57cec5SDimitry Andric       .addReg(SystemZ::R14D);
1450b57cec5SDimitry Andric     break;
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   case SystemZ::CRBReturn:
1480b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CRB)
1490b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
1500b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
1510b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
1520b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
1530b57cec5SDimitry Andric       .addImm(0);
1540b57cec5SDimitry Andric     break;
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   case SystemZ::CGRBReturn:
1570b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CGRB)
1580b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
1590b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
1600b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
1610b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
1620b57cec5SDimitry Andric       .addImm(0);
1630b57cec5SDimitry Andric     break;
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   case SystemZ::CIBReturn:
1660b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CIB)
1670b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
1680b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
1690b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
1700b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
1710b57cec5SDimitry Andric       .addImm(0);
1720b57cec5SDimitry Andric     break;
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric   case SystemZ::CGIBReturn:
1750b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CGIB)
1760b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
1770b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
1780b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
1790b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
1800b57cec5SDimitry Andric       .addImm(0);
1810b57cec5SDimitry Andric     break;
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   case SystemZ::CLRBReturn:
1840b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLRB)
1850b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
1860b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
1870b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
1880b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
1890b57cec5SDimitry Andric       .addImm(0);
1900b57cec5SDimitry Andric     break;
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric   case SystemZ::CLGRBReturn:
1930b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
1940b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
1950b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
1960b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
1970b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
1980b57cec5SDimitry Andric       .addImm(0);
1990b57cec5SDimitry Andric     break;
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric   case SystemZ::CLIBReturn:
2020b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLIB)
2030b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2040b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2050b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2060b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2070b57cec5SDimitry Andric       .addImm(0);
2080b57cec5SDimitry Andric     break;
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   case SystemZ::CLGIBReturn:
2110b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
2120b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2130b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2140b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2150b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2160b57cec5SDimitry Andric       .addImm(0);
2170b57cec5SDimitry Andric     break;
2180b57cec5SDimitry Andric 
219fe6060f1SDimitry Andric   case SystemZ::CallBRASL_XPLINK64:
220fe6060f1SDimitry Andric     EmitToStreamer(*OutStreamer,
221fe6060f1SDimitry Andric                    MCInstBuilder(SystemZ::BRASL)
222fe6060f1SDimitry Andric                        .addReg(SystemZ::R7D)
223fe6060f1SDimitry Andric                        .addExpr(Lower.getExpr(MI->getOperand(0),
224fe6060f1SDimitry Andric                                               MCSymbolRefExpr::VK_PLT)));
225fe6060f1SDimitry Andric     EmitToStreamer(
226fe6060f1SDimitry Andric         *OutStreamer,
227fe6060f1SDimitry Andric         MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R3D));
228fe6060f1SDimitry Andric     return;
229fe6060f1SDimitry Andric 
230fe6060f1SDimitry Andric   case SystemZ::CallBASR_XPLINK64:
231fe6060f1SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
232fe6060f1SDimitry Andric                                      .addReg(SystemZ::R7D)
233fe6060f1SDimitry Andric                                      .addReg(MI->getOperand(0).getReg()));
234fe6060f1SDimitry Andric     EmitToStreamer(
235fe6060f1SDimitry Andric         *OutStreamer,
236fe6060f1SDimitry Andric         MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D));
237fe6060f1SDimitry Andric     return;
238fe6060f1SDimitry Andric 
2390b57cec5SDimitry Andric   case SystemZ::CallBRASL:
2400b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRASL)
2410b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2420b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
2430b57cec5SDimitry Andric     break;
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric   case SystemZ::CallBASR:
2460b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BASR)
2470b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2480b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg());
2490b57cec5SDimitry Andric     break;
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric   case SystemZ::CallJG:
2520b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::JG)
2530b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
2540b57cec5SDimitry Andric     break;
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric   case SystemZ::CallBRCL:
2570b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRCL)
2580b57cec5SDimitry Andric       .addImm(MI->getOperand(0).getImm())
2590b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2600b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT));
2610b57cec5SDimitry Andric     break;
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric   case SystemZ::CallBR:
264e8d8bef9SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BR)
265e8d8bef9SDimitry Andric       .addReg(MI->getOperand(0).getReg());
2660b57cec5SDimitry Andric     break;
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   case SystemZ::CallBCR:
2690b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BCR)
2700b57cec5SDimitry Andric       .addImm(MI->getOperand(0).getImm())
2710b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
272e8d8bef9SDimitry Andric       .addReg(MI->getOperand(2).getReg());
2730b57cec5SDimitry Andric     break;
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric   case SystemZ::CRBCall:
2760b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CRB)
2770b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2780b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
2790b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
280e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
2810b57cec5SDimitry Andric       .addImm(0);
2820b57cec5SDimitry Andric     break;
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   case SystemZ::CGRBCall:
2850b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CGRB)
2860b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2870b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
2880b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
289e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
2900b57cec5SDimitry Andric       .addImm(0);
2910b57cec5SDimitry Andric     break;
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   case SystemZ::CIBCall:
2940b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CIB)
2950b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2960b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2970b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
298e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
2990b57cec5SDimitry Andric       .addImm(0);
3000b57cec5SDimitry Andric     break;
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   case SystemZ::CGIBCall:
3030b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CGIB)
3040b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
3050b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
3060b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
307e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
3080b57cec5SDimitry Andric       .addImm(0);
3090b57cec5SDimitry Andric     break;
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric   case SystemZ::CLRBCall:
3120b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLRB)
3130b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
3140b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
3150b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
316e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
3170b57cec5SDimitry Andric       .addImm(0);
3180b57cec5SDimitry Andric     break;
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric   case SystemZ::CLGRBCall:
3210b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
3220b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
3230b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
3240b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
325e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
3260b57cec5SDimitry Andric       .addImm(0);
3270b57cec5SDimitry Andric     break;
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric   case SystemZ::CLIBCall:
3300b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLIB)
3310b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
3320b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
3330b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
334e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
3350b57cec5SDimitry Andric       .addImm(0);
3360b57cec5SDimitry Andric     break;
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric   case SystemZ::CLGIBCall:
3390b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
3400b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
3410b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
3420b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
343e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
3440b57cec5SDimitry Andric       .addImm(0);
3450b57cec5SDimitry Andric     break;
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   case SystemZ::TLS_GDCALL:
3480b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRASL)
3490b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
3500b57cec5SDimitry Andric       .addExpr(getTLSGetOffset(MF->getContext()))
3510b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD));
3520b57cec5SDimitry Andric     break;
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric   case SystemZ::TLS_LDCALL:
3550b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRASL)
3560b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
3570b57cec5SDimitry Andric       .addExpr(getTLSGetOffset(MF->getContext()))
3580b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM));
3590b57cec5SDimitry Andric     break;
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   case SystemZ::GOT:
3620b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::LARL)
3630b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
3640b57cec5SDimitry Andric       .addExpr(getGlobalOffsetTable(MF->getContext()));
3650b57cec5SDimitry Andric     break;
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   case SystemZ::IILF64:
3680b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::IILF)
3690b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
3700b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm());
3710b57cec5SDimitry Andric     break;
3720b57cec5SDimitry Andric 
3730b57cec5SDimitry Andric   case SystemZ::IIHF64:
3740b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::IIHF)
3750b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
3760b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm());
3770b57cec5SDimitry Andric     break;
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric   case SystemZ::RISBHH:
3800b57cec5SDimitry Andric   case SystemZ::RISBHL:
3810b57cec5SDimitry Andric     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
3820b57cec5SDimitry Andric     break;
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   case SystemZ::RISBLH:
3850b57cec5SDimitry Andric   case SystemZ::RISBLL:
3860b57cec5SDimitry Andric     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
3870b57cec5SDimitry Andric     break;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   case SystemZ::VLVGP32:
3900b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::VLVGP)
3910b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
3920b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg()))
3930b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()));
3940b57cec5SDimitry Andric     break;
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric   case SystemZ::VLR32:
3970b57cec5SDimitry Andric   case SystemZ::VLR64:
3980b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::VLR)
3990b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
4000b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()));
4010b57cec5SDimitry Andric     break;
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric   case SystemZ::VL:
4040b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
4050b57cec5SDimitry Andric     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign);
4060b57cec5SDimitry Andric     break;
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric   case SystemZ::VST:
4090b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
4100b57cec5SDimitry Andric     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign);
4110b57cec5SDimitry Andric     break;
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric   case SystemZ::VLM:
4140b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
4150b57cec5SDimitry Andric     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign);
4160b57cec5SDimitry Andric     break;
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric   case SystemZ::VSTM:
4190b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
4200b57cec5SDimitry Andric     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign);
4210b57cec5SDimitry Andric     break;
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric   case SystemZ::VL32:
4240b57cec5SDimitry Andric     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF);
4250b57cec5SDimitry Andric     break;
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   case SystemZ::VL64:
4280b57cec5SDimitry Andric     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG);
4290b57cec5SDimitry Andric     break;
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric   case SystemZ::VST32:
4320b57cec5SDimitry Andric     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF);
4330b57cec5SDimitry Andric     break;
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   case SystemZ::VST64:
4360b57cec5SDimitry Andric     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG);
4370b57cec5SDimitry Andric     break;
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   case SystemZ::LFER:
4400b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::VLGVF)
4410b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg()))
4420b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()))
4430b57cec5SDimitry Andric       .addReg(0).addImm(0);
4440b57cec5SDimitry Andric     break;
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   case SystemZ::LEFR:
4470b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::VLVGF)
4480b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
4490b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
4500b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
4510b57cec5SDimitry Andric       .addReg(0).addImm(0);
4520b57cec5SDimitry Andric     break;
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric #define LOWER_LOW(NAME)                                                 \
4550b57cec5SDimitry Andric   case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
4560b57cec5SDimitry Andric 
4570b57cec5SDimitry Andric   LOWER_LOW(IILL);
4580b57cec5SDimitry Andric   LOWER_LOW(IILH);
4590b57cec5SDimitry Andric   LOWER_LOW(TMLL);
4600b57cec5SDimitry Andric   LOWER_LOW(TMLH);
4610b57cec5SDimitry Andric   LOWER_LOW(NILL);
4620b57cec5SDimitry Andric   LOWER_LOW(NILH);
4630b57cec5SDimitry Andric   LOWER_LOW(NILF);
4640b57cec5SDimitry Andric   LOWER_LOW(OILL);
4650b57cec5SDimitry Andric   LOWER_LOW(OILH);
4660b57cec5SDimitry Andric   LOWER_LOW(OILF);
4670b57cec5SDimitry Andric   LOWER_LOW(XILF);
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric #undef LOWER_LOW
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric #define LOWER_HIGH(NAME) \
4720b57cec5SDimitry Andric   case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric   LOWER_HIGH(IIHL);
4750b57cec5SDimitry Andric   LOWER_HIGH(IIHH);
4760b57cec5SDimitry Andric   LOWER_HIGH(TMHL);
4770b57cec5SDimitry Andric   LOWER_HIGH(TMHH);
4780b57cec5SDimitry Andric   LOWER_HIGH(NIHL);
4790b57cec5SDimitry Andric   LOWER_HIGH(NIHH);
4800b57cec5SDimitry Andric   LOWER_HIGH(NIHF);
4810b57cec5SDimitry Andric   LOWER_HIGH(OIHL);
4820b57cec5SDimitry Andric   LOWER_HIGH(OIHH);
4830b57cec5SDimitry Andric   LOWER_HIGH(OIHF);
4840b57cec5SDimitry Andric   LOWER_HIGH(XIHF);
4850b57cec5SDimitry Andric 
4860b57cec5SDimitry Andric #undef LOWER_HIGH
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric   case SystemZ::Serialize:
4890b57cec5SDimitry Andric     if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())
4900b57cec5SDimitry Andric       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
4910b57cec5SDimitry Andric         .addImm(14).addReg(SystemZ::R0D);
4920b57cec5SDimitry Andric     else
4930b57cec5SDimitry Andric       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
4940b57cec5SDimitry Andric         .addImm(15).addReg(SystemZ::R0D);
4950b57cec5SDimitry Andric     break;
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric   // Emit nothing here but a comment if we can.
4980b57cec5SDimitry Andric   case SystemZ::MemBarrier:
4990b57cec5SDimitry Andric     OutStreamer->emitRawComment("MEMBARRIER");
5000b57cec5SDimitry Andric     return;
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric   // We want to emit "j .+2" for traps, jumping to the relative immediate field
5030b57cec5SDimitry Andric   // of the jump instruction, which is an illegal instruction. We cannot emit a
5040b57cec5SDimitry Andric   // "." symbol, so create and emit a temp label before the instruction and use
5050b57cec5SDimitry Andric   // that instead.
5060b57cec5SDimitry Andric   case SystemZ::Trap: {
5070b57cec5SDimitry Andric     MCSymbol *DotSym = OutContext.createTempSymbol();
5085ffd83dbSDimitry Andric     OutStreamer->emitLabel(DotSym);
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
5110b57cec5SDimitry Andric     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
5120b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::J)
5130b57cec5SDimitry Andric       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
5140b57cec5SDimitry Andric     }
5150b57cec5SDimitry Andric     break;
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric   // Conditional traps will create a branch on condition instruction that jumps
5180b57cec5SDimitry Andric   // to the relative immediate field of the jump instruction. (eg. "jo .+2")
5190b57cec5SDimitry Andric   case SystemZ::CondTrap: {
5200b57cec5SDimitry Andric     MCSymbol *DotSym = OutContext.createTempSymbol();
5215ffd83dbSDimitry Andric     OutStreamer->emitLabel(DotSym);
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
5240b57cec5SDimitry Andric     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
5250b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRC)
5260b57cec5SDimitry Andric       .addImm(MI->getOperand(0).getImm())
5270b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
5280b57cec5SDimitry Andric       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
5290b57cec5SDimitry Andric     }
5300b57cec5SDimitry Andric     break;
5310b57cec5SDimitry Andric 
5328bcb0991SDimitry Andric   case TargetOpcode::FENTRY_CALL:
5338bcb0991SDimitry Andric     LowerFENTRY_CALL(*MI, Lower);
5348bcb0991SDimitry Andric     return;
5358bcb0991SDimitry Andric 
5360b57cec5SDimitry Andric   case TargetOpcode::STACKMAP:
5370b57cec5SDimitry Andric     LowerSTACKMAP(*MI);
5380b57cec5SDimitry Andric     return;
5390b57cec5SDimitry Andric 
5400b57cec5SDimitry Andric   case TargetOpcode::PATCHPOINT:
5410b57cec5SDimitry Andric     LowerPATCHPOINT(*MI, Lower);
5420b57cec5SDimitry Andric     return;
5430b57cec5SDimitry Andric 
544fe6060f1SDimitry Andric   case SystemZ::EXRL_Pseudo: {
545fe6060f1SDimitry Andric     unsigned TargetInsOpc = MI->getOperand(0).getImm();
546fe6060f1SDimitry Andric     Register LenMinus1Reg = MI->getOperand(1).getReg();
547fe6060f1SDimitry Andric     Register DestReg = MI->getOperand(2).getReg();
548fe6060f1SDimitry Andric     int64_t DestDisp = MI->getOperand(3).getImm();
549fe6060f1SDimitry Andric     Register SrcReg = MI->getOperand(4).getReg();
550fe6060f1SDimitry Andric     int64_t SrcDisp = MI->getOperand(5).getImm();
551fe6060f1SDimitry Andric 
552*349cc55cSDimitry Andric     SystemZTargetStreamer *TS = getTargetStreamer();
553fe6060f1SDimitry Andric     MCSymbol *DotSym = nullptr;
554fe6060f1SDimitry Andric     MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg)
555fe6060f1SDimitry Andric       .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp);
556*349cc55cSDimitry Andric     SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
557*349cc55cSDimitry Andric     SystemZTargetStreamer::EXRLT2SymMap::iterator I =
558*349cc55cSDimitry Andric         TS->EXRLTargets2Sym.find(ET_STI);
559*349cc55cSDimitry Andric     if (I != TS->EXRLTargets2Sym.end())
560fe6060f1SDimitry Andric       DotSym = I->second;
561fe6060f1SDimitry Andric     else
562*349cc55cSDimitry Andric       TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol();
563fe6060f1SDimitry Andric     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
564fe6060f1SDimitry Andric     EmitToStreamer(
565fe6060f1SDimitry Andric         *OutStreamer,
566fe6060f1SDimitry Andric         MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot));
567fe6060f1SDimitry Andric     return;
568fe6060f1SDimitry Andric   }
569fe6060f1SDimitry Andric 
5700b57cec5SDimitry Andric   default:
5710b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
5720b57cec5SDimitry Andric     break;
5730b57cec5SDimitry Andric   }
5740b57cec5SDimitry Andric   EmitToStreamer(*OutStreamer, LoweredMI);
5750b57cec5SDimitry Andric }
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric // Emit the largest nop instruction smaller than or equal to NumBytes
5780b57cec5SDimitry Andric // bytes.  Return the size of nop emitted.
5790b57cec5SDimitry Andric static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
5800b57cec5SDimitry Andric                         unsigned NumBytes, const MCSubtargetInfo &STI) {
5810b57cec5SDimitry Andric   if (NumBytes < 2) {
5820b57cec5SDimitry Andric     llvm_unreachable("Zero nops?");
5830b57cec5SDimitry Andric     return 0;
5840b57cec5SDimitry Andric   }
5850b57cec5SDimitry Andric   else if (NumBytes < 4) {
5865ffd83dbSDimitry Andric     OutStreamer.emitInstruction(
5875ffd83dbSDimitry Andric         MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
5880b57cec5SDimitry Andric     return 2;
5890b57cec5SDimitry Andric   }
5900b57cec5SDimitry Andric   else if (NumBytes < 6) {
5915ffd83dbSDimitry Andric     OutStreamer.emitInstruction(
5925ffd83dbSDimitry Andric         MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
5930b57cec5SDimitry Andric         STI);
5940b57cec5SDimitry Andric     return 4;
5950b57cec5SDimitry Andric   }
5960b57cec5SDimitry Andric   else {
5970b57cec5SDimitry Andric     MCSymbol *DotSym = OutContext.createTempSymbol();
5980b57cec5SDimitry Andric     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
5995ffd83dbSDimitry Andric     OutStreamer.emitLabel(DotSym);
6005ffd83dbSDimitry Andric     OutStreamer.emitInstruction(
6015ffd83dbSDimitry Andric         MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
6020b57cec5SDimitry Andric     return 6;
6030b57cec5SDimitry Andric   }
6040b57cec5SDimitry Andric }
6050b57cec5SDimitry Andric 
6068bcb0991SDimitry Andric void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
6078bcb0991SDimitry Andric                                          SystemZMCInstLower &Lower) {
6088bcb0991SDimitry Andric   MCContext &Ctx = MF->getContext();
609480093f4SDimitry Andric   if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
610480093f4SDimitry Andric     MCSymbol *DotSym = OutContext.createTempSymbol();
611480093f4SDimitry Andric     OutStreamer->PushSection();
612480093f4SDimitry Andric     OutStreamer->SwitchSection(
613480093f4SDimitry Andric         Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
6145ffd83dbSDimitry Andric     OutStreamer->emitSymbolValue(DotSym, 8);
615480093f4SDimitry Andric     OutStreamer->PopSection();
6165ffd83dbSDimitry Andric     OutStreamer->emitLabel(DotSym);
617480093f4SDimitry Andric   }
618480093f4SDimitry Andric 
619480093f4SDimitry Andric   if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
6208bcb0991SDimitry Andric     EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());
6218bcb0991SDimitry Andric     return;
6228bcb0991SDimitry Andric   }
6238bcb0991SDimitry Andric 
6248bcb0991SDimitry Andric   MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
6258bcb0991SDimitry Andric   const MCSymbolRefExpr *Op =
6268bcb0991SDimitry Andric       MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx);
6275ffd83dbSDimitry Andric   OutStreamer->emitInstruction(
6285ffd83dbSDimitry Andric       MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
6295ffd83dbSDimitry Andric       getSubtargetInfo());
6308bcb0991SDimitry Andric }
6318bcb0991SDimitry Andric 
6320b57cec5SDimitry Andric void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
6330b57cec5SDimitry Andric   const SystemZInstrInfo *TII =
6340b57cec5SDimitry Andric     static_cast<const SystemZInstrInfo *>(MF->getSubtarget().getInstrInfo());
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric   unsigned NumNOPBytes = MI.getOperand(1).getImm();
6370b57cec5SDimitry Andric 
638480093f4SDimitry Andric   auto &Ctx = OutStreamer->getContext();
639480093f4SDimitry Andric   MCSymbol *MILabel = Ctx.createTempSymbol();
6405ffd83dbSDimitry Andric   OutStreamer->emitLabel(MILabel);
641480093f4SDimitry Andric 
642480093f4SDimitry Andric   SM.recordStackMap(*MILabel, MI);
6430b57cec5SDimitry Andric   assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric   // Scan ahead to trim the shadow.
6460b57cec5SDimitry Andric   unsigned ShadowBytes = 0;
6470b57cec5SDimitry Andric   const MachineBasicBlock &MBB = *MI.getParent();
6480b57cec5SDimitry Andric   MachineBasicBlock::const_iterator MII(MI);
6490b57cec5SDimitry Andric   ++MII;
6500b57cec5SDimitry Andric   while (ShadowBytes < NumNOPBytes) {
6510b57cec5SDimitry Andric     if (MII == MBB.end() ||
6520b57cec5SDimitry Andric         MII->getOpcode() == TargetOpcode::PATCHPOINT ||
6530b57cec5SDimitry Andric         MII->getOpcode() == TargetOpcode::STACKMAP)
6540b57cec5SDimitry Andric       break;
6550b57cec5SDimitry Andric     ShadowBytes += TII->getInstSizeInBytes(*MII);
6560b57cec5SDimitry Andric     if (MII->isCall())
6570b57cec5SDimitry Andric       break;
6580b57cec5SDimitry Andric     ++MII;
6590b57cec5SDimitry Andric   }
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric   // Emit nops.
6620b57cec5SDimitry Andric   while (ShadowBytes < NumNOPBytes)
6630b57cec5SDimitry Andric     ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
6640b57cec5SDimitry Andric                            getSubtargetInfo());
6650b57cec5SDimitry Andric }
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric // Lower a patchpoint of the form:
6680b57cec5SDimitry Andric // [<def>], <id>, <numBytes>, <target>, <numArgs>
6690b57cec5SDimitry Andric void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
6700b57cec5SDimitry Andric                                         SystemZMCInstLower &Lower) {
671480093f4SDimitry Andric   auto &Ctx = OutStreamer->getContext();
672480093f4SDimitry Andric   MCSymbol *MILabel = Ctx.createTempSymbol();
6735ffd83dbSDimitry Andric   OutStreamer->emitLabel(MILabel);
674480093f4SDimitry Andric 
675480093f4SDimitry Andric   SM.recordPatchPoint(*MILabel, MI);
6760b57cec5SDimitry Andric   PatchPointOpers Opers(&MI);
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric   unsigned EncodedBytes = 0;
6790b57cec5SDimitry Andric   const MachineOperand &CalleeMO = Opers.getCallTarget();
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric   if (CalleeMO.isImm()) {
6820b57cec5SDimitry Andric     uint64_t CallTarget = CalleeMO.getImm();
6830b57cec5SDimitry Andric     if (CallTarget) {
6840b57cec5SDimitry Andric       unsigned ScratchIdx = -1;
6850b57cec5SDimitry Andric       unsigned ScratchReg = 0;
6860b57cec5SDimitry Andric       do {
6870b57cec5SDimitry Andric         ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);
6880b57cec5SDimitry Andric         ScratchReg = MI.getOperand(ScratchIdx).getReg();
6890b57cec5SDimitry Andric       } while (ScratchReg == SystemZ::R0D);
6900b57cec5SDimitry Andric 
6910b57cec5SDimitry Andric       // Materialize the call target address
6920b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
6930b57cec5SDimitry Andric                                       .addReg(ScratchReg)
6940b57cec5SDimitry Andric                                       .addImm(CallTarget & 0xFFFFFFFF));
6950b57cec5SDimitry Andric       EncodedBytes += 6;
6960b57cec5SDimitry Andric       if (CallTarget >> 32) {
6970b57cec5SDimitry Andric         EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
6980b57cec5SDimitry Andric                                         .addReg(ScratchReg)
6990b57cec5SDimitry Andric                                         .addImm(CallTarget >> 32));
7000b57cec5SDimitry Andric         EncodedBytes += 6;
7010b57cec5SDimitry Andric       }
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
7040b57cec5SDimitry Andric                                      .addReg(SystemZ::R14D)
7050b57cec5SDimitry Andric                                      .addReg(ScratchReg));
7060b57cec5SDimitry Andric       EncodedBytes += 2;
7070b57cec5SDimitry Andric     }
7080b57cec5SDimitry Andric   } else if (CalleeMO.isGlobal()) {
7090b57cec5SDimitry Andric     const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT);
7100b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
7110b57cec5SDimitry Andric                                    .addReg(SystemZ::R14D)
7120b57cec5SDimitry Andric                                    .addExpr(Expr));
7130b57cec5SDimitry Andric     EncodedBytes += 6;
7140b57cec5SDimitry Andric   }
7150b57cec5SDimitry Andric 
7160b57cec5SDimitry Andric   // Emit padding.
7170b57cec5SDimitry Andric   unsigned NumBytes = Opers.getNumPatchBytes();
7180b57cec5SDimitry Andric   assert(NumBytes >= EncodedBytes &&
7190b57cec5SDimitry Andric          "Patchpoint can't request size less than the length of a call.");
7200b57cec5SDimitry Andric   assert((NumBytes - EncodedBytes) % 2 == 0 &&
7210b57cec5SDimitry Andric          "Invalid number of NOP bytes requested!");
7220b57cec5SDimitry Andric   while (EncodedBytes < NumBytes)
7230b57cec5SDimitry Andric     EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,
7240b57cec5SDimitry Andric                             getSubtargetInfo());
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric // Convert a SystemZ-specific constant pool modifier into the associated
7280b57cec5SDimitry Andric // MCSymbolRefExpr variant kind.
7290b57cec5SDimitry Andric static MCSymbolRefExpr::VariantKind
7300b57cec5SDimitry Andric getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
7310b57cec5SDimitry Andric   switch (Modifier) {
7320b57cec5SDimitry Andric   case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
7330b57cec5SDimitry Andric   case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM;
7340b57cec5SDimitry Andric   case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF;
7350b57cec5SDimitry Andric   case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
7360b57cec5SDimitry Andric   }
7370b57cec5SDimitry Andric   llvm_unreachable("Invalid SystemCPModifier!");
7380b57cec5SDimitry Andric }
7390b57cec5SDimitry Andric 
7405ffd83dbSDimitry Andric void SystemZAsmPrinter::emitMachineConstantPoolValue(
7415ffd83dbSDimitry Andric     MachineConstantPoolValue *MCPV) {
7420b57cec5SDimitry Andric   auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
7430b57cec5SDimitry Andric 
7440b57cec5SDimitry Andric   const MCExpr *Expr =
7450b57cec5SDimitry Andric     MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()),
7460b57cec5SDimitry Andric                             getModifierVariantKind(ZCPV->getModifier()),
7470b57cec5SDimitry Andric                             OutContext);
7480b57cec5SDimitry Andric   uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
7490b57cec5SDimitry Andric 
7505ffd83dbSDimitry Andric   OutStreamer->emitValue(Expr, Size);
7510b57cec5SDimitry Andric }
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
7540b57cec5SDimitry Andric                                         const char *ExtraCode,
7550b57cec5SDimitry Andric                                         raw_ostream &OS) {
756fe6060f1SDimitry Andric   const MCRegisterInfo &MRI = *TM.getMCRegisterInfo();
757fe6060f1SDimitry Andric   const MachineOperand &MO = MI->getOperand(OpNo);
758fe6060f1SDimitry Andric   MCOperand MCOp;
759fe6060f1SDimitry Andric   if (ExtraCode) {
760fe6060f1SDimitry Andric     if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() &&
761fe6060f1SDimitry Andric         SystemZ::GR128BitRegClass.contains(MO.getReg()))
762fe6060f1SDimitry Andric       MCOp =
763fe6060f1SDimitry Andric           MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64));
764fe6060f1SDimitry Andric     else
7650b57cec5SDimitry Andric       return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
766fe6060f1SDimitry Andric   } else {
7670b57cec5SDimitry Andric     SystemZMCInstLower Lower(MF->getContext(), *this);
768fe6060f1SDimitry Andric     MCOp = Lower.lowerOperand(MO);
769fe6060f1SDimitry Andric   }
770fe6060f1SDimitry Andric   SystemZInstPrinter::printOperand(MCOp, MAI, OS);
7710b57cec5SDimitry Andric   return false;
7720b57cec5SDimitry Andric }
7730b57cec5SDimitry Andric 
7740b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
7750b57cec5SDimitry Andric                                               unsigned OpNo,
7760b57cec5SDimitry Andric                                               const char *ExtraCode,
7770b57cec5SDimitry Andric                                               raw_ostream &OS) {
778*349cc55cSDimitry Andric   SystemZInstPrinter::
779*349cc55cSDimitry Andric     printAddress(MAI, MI->getOperand(OpNo).getReg(),
780*349cc55cSDimitry Andric                  MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()),
7810b57cec5SDimitry Andric                  MI->getOperand(OpNo + 2).getReg(), OS);
7820b57cec5SDimitry Andric   return false;
7830b57cec5SDimitry Andric }
7840b57cec5SDimitry Andric 
7855ffd83dbSDimitry Andric void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
7860b57cec5SDimitry Andric   emitStackMaps(SM);
7870b57cec5SDimitry Andric }
7880b57cec5SDimitry Andric 
7890b57cec5SDimitry Andric // Force static initialization.
790480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() {
7910b57cec5SDimitry Andric   RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget());
7920b57cec5SDimitry Andric }
793