xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric //===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Streams SystemZ assembly language and associated data, in the form of
100b57cec5SDimitry Andric // MCInsts and MCExprs respectively.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "SystemZAsmPrinter.h"
150b57cec5SDimitry Andric #include "MCTargetDesc/SystemZInstPrinter.h"
160b57cec5SDimitry Andric #include "SystemZConstantPoolValue.h"
170b57cec5SDimitry Andric #include "SystemZMCInstLower.h"
180b57cec5SDimitry Andric #include "TargetInfo/SystemZTargetInfo.h"
19480093f4SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
220b57cec5SDimitry Andric #include "llvm/IR/Mangler.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCInstBuilder.h"
25480093f4SDimitry Andric #include "llvm/MC/MCSectionELF.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
27349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric using namespace llvm;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the
320b57cec5SDimitry Andric // GR64 register operands turned into GR32s.
330b57cec5SDimitry Andric static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {
340b57cec5SDimitry Andric   if (MI->isCompare())
350b57cec5SDimitry Andric     return MCInstBuilder(Opcode)
360b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
370b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm());
380b57cec5SDimitry Andric   else
390b57cec5SDimitry Andric     return MCInstBuilder(Opcode)
400b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
410b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg()))
420b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm());
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the
460b57cec5SDimitry Andric // GR64 register operands turned into GRH32s.
470b57cec5SDimitry Andric static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) {
480b57cec5SDimitry Andric   if (MI->isCompare())
490b57cec5SDimitry Andric     return MCInstBuilder(Opcode)
500b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
510b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm());
520b57cec5SDimitry Andric   else
530b57cec5SDimitry Andric     return MCInstBuilder(Opcode)
540b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
550b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg()))
560b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm());
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the
600b57cec5SDimitry Andric // R2 register turned into a GR64.
610b57cec5SDimitry Andric static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {
620b57cec5SDimitry Andric   return MCInstBuilder(Opcode)
630b57cec5SDimitry Andric     .addReg(MI->getOperand(0).getReg())
640b57cec5SDimitry Andric     .addReg(MI->getOperand(1).getReg())
650b57cec5SDimitry Andric     .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()))
660b57cec5SDimitry Andric     .addImm(MI->getOperand(3).getImm())
670b57cec5SDimitry Andric     .addImm(MI->getOperand(4).getImm())
680b57cec5SDimitry Andric     .addImm(MI->getOperand(5).getImm());
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
720b57cec5SDimitry Andric   StringRef Name = "__tls_get_offset";
730b57cec5SDimitry Andric   return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
740b57cec5SDimitry Andric                                  MCSymbolRefExpr::VK_PLT,
750b57cec5SDimitry Andric                                  Context);
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) {
790b57cec5SDimitry Andric   StringRef Name = "_GLOBAL_OFFSET_TABLE_";
800b57cec5SDimitry Andric   return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
810b57cec5SDimitry Andric                                  MCSymbolRefExpr::VK_None,
820b57cec5SDimitry Andric                                  Context);
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric // MI is an instruction that accepts an optional alignment hint,
860b57cec5SDimitry Andric // and which was already lowered to LoweredMI.  If the alignment
870b57cec5SDimitry Andric // of the original memory operand is known, update LoweredMI to
880b57cec5SDimitry Andric // an instruction with the corresponding hint set.
890b57cec5SDimitry Andric static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI,
900b57cec5SDimitry Andric                                unsigned Opcode) {
9181ad6265SDimitry Andric   if (MI->memoperands_empty())
920b57cec5SDimitry Andric     return;
9381ad6265SDimitry Andric 
9481ad6265SDimitry Andric   Align Alignment = Align(16);
9581ad6265SDimitry Andric   for (MachineInstr::mmo_iterator MMOI = MI->memoperands_begin(),
9681ad6265SDimitry Andric          EE = MI->memoperands_end(); MMOI != EE; ++MMOI)
9781ad6265SDimitry Andric     if ((*MMOI)->getAlign() < Alignment)
9881ad6265SDimitry Andric       Alignment = (*MMOI)->getAlign();
9981ad6265SDimitry Andric 
1000b57cec5SDimitry Andric   unsigned AlignmentHint = 0;
10181ad6265SDimitry Andric   if (Alignment >= Align(16))
1020b57cec5SDimitry Andric     AlignmentHint = 4;
10381ad6265SDimitry Andric   else if (Alignment >= Align(8))
1040b57cec5SDimitry Andric     AlignmentHint = 3;
1050b57cec5SDimitry Andric   if (AlignmentHint == 0)
1060b57cec5SDimitry Andric     return;
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   LoweredMI.setOpcode(Opcode);
1090b57cec5SDimitry Andric   LoweredMI.addOperand(MCOperand::createImm(AlignmentHint));
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric // MI loads the high part of a vector from memory.  Return an instruction
1130b57cec5SDimitry Andric // that uses replicating vector load Opcode to do the same thing.
1140b57cec5SDimitry Andric static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) {
1150b57cec5SDimitry Andric   return MCInstBuilder(Opcode)
1160b57cec5SDimitry Andric     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
1170b57cec5SDimitry Andric     .addReg(MI->getOperand(1).getReg())
1180b57cec5SDimitry Andric     .addImm(MI->getOperand(2).getImm())
1190b57cec5SDimitry Andric     .addReg(MI->getOperand(3).getReg());
1200b57cec5SDimitry Andric }
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric // MI stores the high part of a vector to memory.  Return an instruction
1230b57cec5SDimitry Andric // that uses elemental vector store Opcode to do the same thing.
1240b57cec5SDimitry Andric static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {
1250b57cec5SDimitry Andric   return MCInstBuilder(Opcode)
1260b57cec5SDimitry Andric     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
1270b57cec5SDimitry Andric     .addReg(MI->getOperand(1).getReg())
1280b57cec5SDimitry Andric     .addImm(MI->getOperand(2).getImm())
1290b57cec5SDimitry Andric     .addReg(MI->getOperand(3).getReg())
1300b57cec5SDimitry Andric     .addImm(0);
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric 
13381ad6265SDimitry Andric // The XPLINK ABI requires that a no-op encoding the call type is emitted after
13481ad6265SDimitry Andric // each call to a subroutine. This information can be used by the called
13581ad6265SDimitry Andric // function to determine its entry point, e.g. for generating a backtrace. The
13681ad6265SDimitry Andric // call type is encoded as a register number in the bcr instruction. See
13781ad6265SDimitry Andric // enumeration CallType for the possible values.
13881ad6265SDimitry Andric void SystemZAsmPrinter::emitCallInformation(CallType CT) {
13981ad6265SDimitry Andric   EmitToStreamer(*OutStreamer,
14081ad6265SDimitry Andric                  MCInstBuilder(SystemZ::BCRAsm)
14181ad6265SDimitry Andric                      .addImm(0)
14281ad6265SDimitry Andric                      .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)]));
14381ad6265SDimitry Andric }
14481ad6265SDimitry Andric 
1455ffd83dbSDimitry Andric void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
146753f127fSDimitry Andric   SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(),
147753f127fSDimitry Andric                                           getSubtargetInfo().getFeatureBits());
148753f127fSDimitry Andric 
1490b57cec5SDimitry Andric   SystemZMCInstLower Lower(MF->getContext(), *this);
1500b57cec5SDimitry Andric   MCInst LoweredMI;
1510b57cec5SDimitry Andric   switch (MI->getOpcode()) {
1520b57cec5SDimitry Andric   case SystemZ::Return:
15381ad6265SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BR)
15481ad6265SDimitry Andric       .addReg(SystemZ::R14D);
15581ad6265SDimitry Andric     break;
15681ad6265SDimitry Andric 
15781ad6265SDimitry Andric   case SystemZ::Return_XPLINK:
15881ad6265SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::B)
15981ad6265SDimitry Andric       .addReg(SystemZ::R7D)
16081ad6265SDimitry Andric       .addImm(2)
16181ad6265SDimitry Andric       .addReg(0);
1620b57cec5SDimitry Andric     break;
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   case SystemZ::CondReturn:
1650b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BCR)
1660b57cec5SDimitry Andric       .addImm(MI->getOperand(0).getImm())
1670b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
1680b57cec5SDimitry Andric       .addReg(SystemZ::R14D);
1690b57cec5SDimitry Andric     break;
1700b57cec5SDimitry Andric 
17181ad6265SDimitry Andric   case SystemZ::CondReturn_XPLINK:
17281ad6265SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BC)
17381ad6265SDimitry Andric       .addImm(MI->getOperand(0).getImm())
17481ad6265SDimitry Andric       .addImm(MI->getOperand(1).getImm())
17581ad6265SDimitry Andric       .addReg(SystemZ::R7D)
17681ad6265SDimitry Andric       .addImm(2)
17781ad6265SDimitry Andric       .addReg(0);
17881ad6265SDimitry Andric     break;
17981ad6265SDimitry Andric 
1800b57cec5SDimitry Andric   case SystemZ::CRBReturn:
1810b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CRB)
1820b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
1830b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
1840b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
1850b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
1860b57cec5SDimitry Andric       .addImm(0);
1870b57cec5SDimitry Andric     break;
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   case SystemZ::CGRBReturn:
1900b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CGRB)
1910b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
1920b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
1930b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
1940b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
1950b57cec5SDimitry Andric       .addImm(0);
1960b57cec5SDimitry Andric     break;
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   case SystemZ::CIBReturn:
1990b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CIB)
2000b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2010b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2020b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2030b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2040b57cec5SDimitry Andric       .addImm(0);
2050b57cec5SDimitry Andric     break;
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   case SystemZ::CGIBReturn:
2080b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CGIB)
2090b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2100b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2110b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2120b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2130b57cec5SDimitry Andric       .addImm(0);
2140b57cec5SDimitry Andric     break;
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   case SystemZ::CLRBReturn:
2170b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLRB)
2180b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2190b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
2200b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2210b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2220b57cec5SDimitry Andric       .addImm(0);
2230b57cec5SDimitry Andric     break;
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   case SystemZ::CLGRBReturn:
2260b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
2270b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2280b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
2290b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2300b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2310b57cec5SDimitry Andric       .addImm(0);
2320b57cec5SDimitry Andric     break;
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric   case SystemZ::CLIBReturn:
2350b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLIB)
2360b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2370b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2380b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2390b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2400b57cec5SDimitry Andric       .addImm(0);
2410b57cec5SDimitry Andric     break;
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   case SystemZ::CLGIBReturn:
2440b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
2450b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2460b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2470b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2480b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2490b57cec5SDimitry Andric       .addImm(0);
2500b57cec5SDimitry Andric     break;
2510b57cec5SDimitry Andric 
252fe6060f1SDimitry Andric   case SystemZ::CallBRASL_XPLINK64:
253fe6060f1SDimitry Andric     EmitToStreamer(*OutStreamer,
254fe6060f1SDimitry Andric                    MCInstBuilder(SystemZ::BRASL)
255fe6060f1SDimitry Andric                        .addReg(SystemZ::R7D)
256fe6060f1SDimitry Andric                        .addExpr(Lower.getExpr(MI->getOperand(0),
257fe6060f1SDimitry Andric                                               MCSymbolRefExpr::VK_PLT)));
25881ad6265SDimitry Andric     emitCallInformation(CallType::BRASL7);
259fe6060f1SDimitry Andric     return;
260fe6060f1SDimitry Andric 
261fe6060f1SDimitry Andric   case SystemZ::CallBASR_XPLINK64:
262fe6060f1SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
263fe6060f1SDimitry Andric                                      .addReg(SystemZ::R7D)
264fe6060f1SDimitry Andric                                      .addReg(MI->getOperand(0).getReg()));
26581ad6265SDimitry Andric     emitCallInformation(CallType::BASR76);
26681ad6265SDimitry Andric     return;
26781ad6265SDimitry Andric 
26881ad6265SDimitry Andric   case SystemZ::CallBASR_STACKEXT:
26981ad6265SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
27081ad6265SDimitry Andric                                      .addReg(SystemZ::R3D)
27181ad6265SDimitry Andric                                      .addReg(MI->getOperand(0).getReg()));
27281ad6265SDimitry Andric     emitCallInformation(CallType::BASR33);
273fe6060f1SDimitry Andric     return;
274fe6060f1SDimitry Andric 
2750b57cec5SDimitry Andric   case SystemZ::CallBRASL:
2760b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRASL)
2770b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2780b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
2790b57cec5SDimitry Andric     break;
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   case SystemZ::CallBASR:
2820b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BASR)
2830b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2840b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg());
2850b57cec5SDimitry Andric     break;
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric   case SystemZ::CallJG:
2880b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::JG)
2890b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
2900b57cec5SDimitry Andric     break;
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric   case SystemZ::CallBRCL:
2930b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRCL)
2940b57cec5SDimitry Andric       .addImm(MI->getOperand(0).getImm())
2950b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2960b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT));
2970b57cec5SDimitry Andric     break;
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   case SystemZ::CallBR:
300e8d8bef9SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BR)
301e8d8bef9SDimitry Andric       .addReg(MI->getOperand(0).getReg());
3020b57cec5SDimitry Andric     break;
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric   case SystemZ::CallBCR:
3050b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BCR)
3060b57cec5SDimitry Andric       .addImm(MI->getOperand(0).getImm())
3070b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
308e8d8bef9SDimitry Andric       .addReg(MI->getOperand(2).getReg());
3090b57cec5SDimitry Andric     break;
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric   case SystemZ::CRBCall:
3120b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CRB)
3130b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
3140b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
3150b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
316e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
3170b57cec5SDimitry Andric       .addImm(0);
3180b57cec5SDimitry Andric     break;
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric   case SystemZ::CGRBCall:
3210b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CGRB)
3220b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
3230b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
3240b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
325e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
3260b57cec5SDimitry Andric       .addImm(0);
3270b57cec5SDimitry Andric     break;
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric   case SystemZ::CIBCall:
3300b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CIB)
3310b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
3320b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
3330b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
334e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
3350b57cec5SDimitry Andric       .addImm(0);
3360b57cec5SDimitry Andric     break;
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric   case SystemZ::CGIBCall:
3390b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CGIB)
3400b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
3410b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
3420b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
343e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
3440b57cec5SDimitry Andric       .addImm(0);
3450b57cec5SDimitry Andric     break;
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   case SystemZ::CLRBCall:
3480b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLRB)
3490b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
3500b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
3510b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
352e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
3530b57cec5SDimitry Andric       .addImm(0);
3540b57cec5SDimitry Andric     break;
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric   case SystemZ::CLGRBCall:
3570b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
3580b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
3590b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
3600b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
361e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
3620b57cec5SDimitry Andric       .addImm(0);
3630b57cec5SDimitry Andric     break;
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric   case SystemZ::CLIBCall:
3660b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLIB)
3670b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
3680b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
3690b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
370e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
3710b57cec5SDimitry Andric       .addImm(0);
3720b57cec5SDimitry Andric     break;
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   case SystemZ::CLGIBCall:
3750b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
3760b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
3770b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
3780b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
379e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
3800b57cec5SDimitry Andric       .addImm(0);
3810b57cec5SDimitry Andric     break;
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric   case SystemZ::TLS_GDCALL:
3840b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRASL)
3850b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
3860b57cec5SDimitry Andric       .addExpr(getTLSGetOffset(MF->getContext()))
3870b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD));
3880b57cec5SDimitry Andric     break;
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric   case SystemZ::TLS_LDCALL:
3910b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRASL)
3920b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
3930b57cec5SDimitry Andric       .addExpr(getTLSGetOffset(MF->getContext()))
3940b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM));
3950b57cec5SDimitry Andric     break;
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric   case SystemZ::GOT:
3980b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::LARL)
3990b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4000b57cec5SDimitry Andric       .addExpr(getGlobalOffsetTable(MF->getContext()));
4010b57cec5SDimitry Andric     break;
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric   case SystemZ::IILF64:
4040b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::IILF)
4050b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
4060b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm());
4070b57cec5SDimitry Andric     break;
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric   case SystemZ::IIHF64:
4100b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::IIHF)
4110b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
4120b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm());
4130b57cec5SDimitry Andric     break;
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric   case SystemZ::RISBHH:
4160b57cec5SDimitry Andric   case SystemZ::RISBHL:
4170b57cec5SDimitry Andric     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
4180b57cec5SDimitry Andric     break;
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric   case SystemZ::RISBLH:
4210b57cec5SDimitry Andric   case SystemZ::RISBLL:
4220b57cec5SDimitry Andric     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
4230b57cec5SDimitry Andric     break;
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric   case SystemZ::VLVGP32:
4260b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::VLVGP)
4270b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4280b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg()))
4290b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()));
4300b57cec5SDimitry Andric     break;
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric   case SystemZ::VLR32:
4330b57cec5SDimitry Andric   case SystemZ::VLR64:
4340b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::VLR)
4350b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
4360b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()));
4370b57cec5SDimitry Andric     break;
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   case SystemZ::VL:
4400b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
4410b57cec5SDimitry Andric     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign);
4420b57cec5SDimitry Andric     break;
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric   case SystemZ::VST:
4450b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
4460b57cec5SDimitry Andric     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign);
4470b57cec5SDimitry Andric     break;
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric   case SystemZ::VLM:
4500b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
4510b57cec5SDimitry Andric     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign);
4520b57cec5SDimitry Andric     break;
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric   case SystemZ::VSTM:
4550b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
4560b57cec5SDimitry Andric     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign);
4570b57cec5SDimitry Andric     break;
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric   case SystemZ::VL32:
4600b57cec5SDimitry Andric     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF);
4610b57cec5SDimitry Andric     break;
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric   case SystemZ::VL64:
4640b57cec5SDimitry Andric     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG);
4650b57cec5SDimitry Andric     break;
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric   case SystemZ::VST32:
4680b57cec5SDimitry Andric     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF);
4690b57cec5SDimitry Andric     break;
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric   case SystemZ::VST64:
4720b57cec5SDimitry Andric     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG);
4730b57cec5SDimitry Andric     break;
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric   case SystemZ::LFER:
4760b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::VLGVF)
4770b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg()))
4780b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()))
4790b57cec5SDimitry Andric       .addReg(0).addImm(0);
4800b57cec5SDimitry Andric     break;
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric   case SystemZ::LEFR:
4830b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::VLVGF)
4840b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
4850b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
4860b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
4870b57cec5SDimitry Andric       .addReg(0).addImm(0);
4880b57cec5SDimitry Andric     break;
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric #define LOWER_LOW(NAME)                                                 \
4910b57cec5SDimitry Andric   case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
4920b57cec5SDimitry Andric 
4930b57cec5SDimitry Andric   LOWER_LOW(IILL);
4940b57cec5SDimitry Andric   LOWER_LOW(IILH);
4950b57cec5SDimitry Andric   LOWER_LOW(TMLL);
4960b57cec5SDimitry Andric   LOWER_LOW(TMLH);
4970b57cec5SDimitry Andric   LOWER_LOW(NILL);
4980b57cec5SDimitry Andric   LOWER_LOW(NILH);
4990b57cec5SDimitry Andric   LOWER_LOW(NILF);
5000b57cec5SDimitry Andric   LOWER_LOW(OILL);
5010b57cec5SDimitry Andric   LOWER_LOW(OILH);
5020b57cec5SDimitry Andric   LOWER_LOW(OILF);
5030b57cec5SDimitry Andric   LOWER_LOW(XILF);
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric #undef LOWER_LOW
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric #define LOWER_HIGH(NAME) \
5080b57cec5SDimitry Andric   case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric   LOWER_HIGH(IIHL);
5110b57cec5SDimitry Andric   LOWER_HIGH(IIHH);
5120b57cec5SDimitry Andric   LOWER_HIGH(TMHL);
5130b57cec5SDimitry Andric   LOWER_HIGH(TMHH);
5140b57cec5SDimitry Andric   LOWER_HIGH(NIHL);
5150b57cec5SDimitry Andric   LOWER_HIGH(NIHH);
5160b57cec5SDimitry Andric   LOWER_HIGH(NIHF);
5170b57cec5SDimitry Andric   LOWER_HIGH(OIHL);
5180b57cec5SDimitry Andric   LOWER_HIGH(OIHH);
5190b57cec5SDimitry Andric   LOWER_HIGH(OIHF);
5200b57cec5SDimitry Andric   LOWER_HIGH(XIHF);
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric #undef LOWER_HIGH
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric   case SystemZ::Serialize:
5250b57cec5SDimitry Andric     if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())
5260b57cec5SDimitry Andric       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
5270b57cec5SDimitry Andric         .addImm(14).addReg(SystemZ::R0D);
5280b57cec5SDimitry Andric     else
5290b57cec5SDimitry Andric       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
5300b57cec5SDimitry Andric         .addImm(15).addReg(SystemZ::R0D);
5310b57cec5SDimitry Andric     break;
5320b57cec5SDimitry Andric 
5330b57cec5SDimitry Andric   // We want to emit "j .+2" for traps, jumping to the relative immediate field
5340b57cec5SDimitry Andric   // of the jump instruction, which is an illegal instruction. We cannot emit a
5350b57cec5SDimitry Andric   // "." symbol, so create and emit a temp label before the instruction and use
5360b57cec5SDimitry Andric   // that instead.
5370b57cec5SDimitry Andric   case SystemZ::Trap: {
5380b57cec5SDimitry Andric     MCSymbol *DotSym = OutContext.createTempSymbol();
5395ffd83dbSDimitry Andric     OutStreamer->emitLabel(DotSym);
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
5420b57cec5SDimitry Andric     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
5430b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::J)
5440b57cec5SDimitry Andric       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
5450b57cec5SDimitry Andric     }
5460b57cec5SDimitry Andric     break;
5470b57cec5SDimitry Andric 
5480b57cec5SDimitry Andric   // Conditional traps will create a branch on condition instruction that jumps
5490b57cec5SDimitry Andric   // to the relative immediate field of the jump instruction. (eg. "jo .+2")
5500b57cec5SDimitry Andric   case SystemZ::CondTrap: {
5510b57cec5SDimitry Andric     MCSymbol *DotSym = OutContext.createTempSymbol();
5525ffd83dbSDimitry Andric     OutStreamer->emitLabel(DotSym);
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
5550b57cec5SDimitry Andric     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
5560b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRC)
5570b57cec5SDimitry Andric       .addImm(MI->getOperand(0).getImm())
5580b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
5590b57cec5SDimitry Andric       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
5600b57cec5SDimitry Andric     }
5610b57cec5SDimitry Andric     break;
5620b57cec5SDimitry Andric 
5638bcb0991SDimitry Andric   case TargetOpcode::FENTRY_CALL:
5648bcb0991SDimitry Andric     LowerFENTRY_CALL(*MI, Lower);
5658bcb0991SDimitry Andric     return;
5668bcb0991SDimitry Andric 
5670b57cec5SDimitry Andric   case TargetOpcode::STACKMAP:
5680b57cec5SDimitry Andric     LowerSTACKMAP(*MI);
5690b57cec5SDimitry Andric     return;
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric   case TargetOpcode::PATCHPOINT:
5720b57cec5SDimitry Andric     LowerPATCHPOINT(*MI, Lower);
5730b57cec5SDimitry Andric     return;
5740b57cec5SDimitry Andric 
575fe6060f1SDimitry Andric   case SystemZ::EXRL_Pseudo: {
576fe6060f1SDimitry Andric     unsigned TargetInsOpc = MI->getOperand(0).getImm();
577fe6060f1SDimitry Andric     Register LenMinus1Reg = MI->getOperand(1).getReg();
578fe6060f1SDimitry Andric     Register DestReg = MI->getOperand(2).getReg();
579fe6060f1SDimitry Andric     int64_t DestDisp = MI->getOperand(3).getImm();
580fe6060f1SDimitry Andric     Register SrcReg = MI->getOperand(4).getReg();
581fe6060f1SDimitry Andric     int64_t SrcDisp = MI->getOperand(5).getImm();
582fe6060f1SDimitry Andric 
583349cc55cSDimitry Andric     SystemZTargetStreamer *TS = getTargetStreamer();
584fe6060f1SDimitry Andric     MCSymbol *DotSym = nullptr;
585fe6060f1SDimitry Andric     MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg)
586fe6060f1SDimitry Andric       .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp);
587349cc55cSDimitry Andric     SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
588349cc55cSDimitry Andric     SystemZTargetStreamer::EXRLT2SymMap::iterator I =
589349cc55cSDimitry Andric         TS->EXRLTargets2Sym.find(ET_STI);
590349cc55cSDimitry Andric     if (I != TS->EXRLTargets2Sym.end())
591fe6060f1SDimitry Andric       DotSym = I->second;
592fe6060f1SDimitry Andric     else
593349cc55cSDimitry Andric       TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol();
594fe6060f1SDimitry Andric     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
595fe6060f1SDimitry Andric     EmitToStreamer(
596fe6060f1SDimitry Andric         *OutStreamer,
597fe6060f1SDimitry Andric         MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot));
598fe6060f1SDimitry Andric     return;
599fe6060f1SDimitry Andric   }
600fe6060f1SDimitry Andric 
6010b57cec5SDimitry Andric   default:
6020b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
6030b57cec5SDimitry Andric     break;
6040b57cec5SDimitry Andric   }
6050b57cec5SDimitry Andric   EmitToStreamer(*OutStreamer, LoweredMI);
6060b57cec5SDimitry Andric }
6070b57cec5SDimitry Andric 
6080b57cec5SDimitry Andric // Emit the largest nop instruction smaller than or equal to NumBytes
6090b57cec5SDimitry Andric // bytes.  Return the size of nop emitted.
6100b57cec5SDimitry Andric static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
6110b57cec5SDimitry Andric                         unsigned NumBytes, const MCSubtargetInfo &STI) {
6120b57cec5SDimitry Andric   if (NumBytes < 2) {
6130b57cec5SDimitry Andric     llvm_unreachable("Zero nops?");
6140b57cec5SDimitry Andric     return 0;
6150b57cec5SDimitry Andric   }
6160b57cec5SDimitry Andric   else if (NumBytes < 4) {
6175ffd83dbSDimitry Andric     OutStreamer.emitInstruction(
6185ffd83dbSDimitry Andric         MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
6190b57cec5SDimitry Andric     return 2;
6200b57cec5SDimitry Andric   }
6210b57cec5SDimitry Andric   else if (NumBytes < 6) {
6225ffd83dbSDimitry Andric     OutStreamer.emitInstruction(
6235ffd83dbSDimitry Andric         MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
6240b57cec5SDimitry Andric         STI);
6250b57cec5SDimitry Andric     return 4;
6260b57cec5SDimitry Andric   }
6270b57cec5SDimitry Andric   else {
6280b57cec5SDimitry Andric     MCSymbol *DotSym = OutContext.createTempSymbol();
6290b57cec5SDimitry Andric     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
6305ffd83dbSDimitry Andric     OutStreamer.emitLabel(DotSym);
6315ffd83dbSDimitry Andric     OutStreamer.emitInstruction(
6325ffd83dbSDimitry Andric         MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
6330b57cec5SDimitry Andric     return 6;
6340b57cec5SDimitry Andric   }
6350b57cec5SDimitry Andric }
6360b57cec5SDimitry Andric 
6378bcb0991SDimitry Andric void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
6388bcb0991SDimitry Andric                                          SystemZMCInstLower &Lower) {
6398bcb0991SDimitry Andric   MCContext &Ctx = MF->getContext();
640480093f4SDimitry Andric   if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
641480093f4SDimitry Andric     MCSymbol *DotSym = OutContext.createTempSymbol();
64281ad6265SDimitry Andric     OutStreamer->pushSection();
64381ad6265SDimitry Andric     OutStreamer->switchSection(
644480093f4SDimitry Andric         Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
6455ffd83dbSDimitry Andric     OutStreamer->emitSymbolValue(DotSym, 8);
64681ad6265SDimitry Andric     OutStreamer->popSection();
6475ffd83dbSDimitry Andric     OutStreamer->emitLabel(DotSym);
648480093f4SDimitry Andric   }
649480093f4SDimitry Andric 
650480093f4SDimitry Andric   if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
6518bcb0991SDimitry Andric     EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());
6528bcb0991SDimitry Andric     return;
6538bcb0991SDimitry Andric   }
6548bcb0991SDimitry Andric 
6558bcb0991SDimitry Andric   MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
6568bcb0991SDimitry Andric   const MCSymbolRefExpr *Op =
6578bcb0991SDimitry Andric       MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx);
6585ffd83dbSDimitry Andric   OutStreamer->emitInstruction(
6595ffd83dbSDimitry Andric       MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
6605ffd83dbSDimitry Andric       getSubtargetInfo());
6618bcb0991SDimitry Andric }
6628bcb0991SDimitry Andric 
6630b57cec5SDimitry Andric void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
66481ad6265SDimitry Andric   auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo();
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric   unsigned NumNOPBytes = MI.getOperand(1).getImm();
6670b57cec5SDimitry Andric 
668480093f4SDimitry Andric   auto &Ctx = OutStreamer->getContext();
669480093f4SDimitry Andric   MCSymbol *MILabel = Ctx.createTempSymbol();
6705ffd83dbSDimitry Andric   OutStreamer->emitLabel(MILabel);
671480093f4SDimitry Andric 
672480093f4SDimitry Andric   SM.recordStackMap(*MILabel, MI);
6730b57cec5SDimitry Andric   assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric   // Scan ahead to trim the shadow.
6760b57cec5SDimitry Andric   unsigned ShadowBytes = 0;
6770b57cec5SDimitry Andric   const MachineBasicBlock &MBB = *MI.getParent();
6780b57cec5SDimitry Andric   MachineBasicBlock::const_iterator MII(MI);
6790b57cec5SDimitry Andric   ++MII;
6800b57cec5SDimitry Andric   while (ShadowBytes < NumNOPBytes) {
6810b57cec5SDimitry Andric     if (MII == MBB.end() ||
6820b57cec5SDimitry Andric         MII->getOpcode() == TargetOpcode::PATCHPOINT ||
6830b57cec5SDimitry Andric         MII->getOpcode() == TargetOpcode::STACKMAP)
6840b57cec5SDimitry Andric       break;
6850b57cec5SDimitry Andric     ShadowBytes += TII->getInstSizeInBytes(*MII);
6860b57cec5SDimitry Andric     if (MII->isCall())
6870b57cec5SDimitry Andric       break;
6880b57cec5SDimitry Andric     ++MII;
6890b57cec5SDimitry Andric   }
6900b57cec5SDimitry Andric 
6910b57cec5SDimitry Andric   // Emit nops.
6920b57cec5SDimitry Andric   while (ShadowBytes < NumNOPBytes)
6930b57cec5SDimitry Andric     ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
6940b57cec5SDimitry Andric                            getSubtargetInfo());
6950b57cec5SDimitry Andric }
6960b57cec5SDimitry Andric 
6970b57cec5SDimitry Andric // Lower a patchpoint of the form:
6980b57cec5SDimitry Andric // [<def>], <id>, <numBytes>, <target>, <numArgs>
6990b57cec5SDimitry Andric void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
7000b57cec5SDimitry Andric                                         SystemZMCInstLower &Lower) {
701480093f4SDimitry Andric   auto &Ctx = OutStreamer->getContext();
702480093f4SDimitry Andric   MCSymbol *MILabel = Ctx.createTempSymbol();
7035ffd83dbSDimitry Andric   OutStreamer->emitLabel(MILabel);
704480093f4SDimitry Andric 
705480093f4SDimitry Andric   SM.recordPatchPoint(*MILabel, MI);
7060b57cec5SDimitry Andric   PatchPointOpers Opers(&MI);
7070b57cec5SDimitry Andric 
7080b57cec5SDimitry Andric   unsigned EncodedBytes = 0;
7090b57cec5SDimitry Andric   const MachineOperand &CalleeMO = Opers.getCallTarget();
7100b57cec5SDimitry Andric 
7110b57cec5SDimitry Andric   if (CalleeMO.isImm()) {
7120b57cec5SDimitry Andric     uint64_t CallTarget = CalleeMO.getImm();
7130b57cec5SDimitry Andric     if (CallTarget) {
7140b57cec5SDimitry Andric       unsigned ScratchIdx = -1;
7150b57cec5SDimitry Andric       unsigned ScratchReg = 0;
7160b57cec5SDimitry Andric       do {
7170b57cec5SDimitry Andric         ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);
7180b57cec5SDimitry Andric         ScratchReg = MI.getOperand(ScratchIdx).getReg();
7190b57cec5SDimitry Andric       } while (ScratchReg == SystemZ::R0D);
7200b57cec5SDimitry Andric 
7210b57cec5SDimitry Andric       // Materialize the call target address
7220b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
7230b57cec5SDimitry Andric                                       .addReg(ScratchReg)
7240b57cec5SDimitry Andric                                       .addImm(CallTarget & 0xFFFFFFFF));
7250b57cec5SDimitry Andric       EncodedBytes += 6;
7260b57cec5SDimitry Andric       if (CallTarget >> 32) {
7270b57cec5SDimitry Andric         EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
7280b57cec5SDimitry Andric                                         .addReg(ScratchReg)
7290b57cec5SDimitry Andric                                         .addImm(CallTarget >> 32));
7300b57cec5SDimitry Andric         EncodedBytes += 6;
7310b57cec5SDimitry Andric       }
7320b57cec5SDimitry Andric 
7330b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
7340b57cec5SDimitry Andric                                      .addReg(SystemZ::R14D)
7350b57cec5SDimitry Andric                                      .addReg(ScratchReg));
7360b57cec5SDimitry Andric       EncodedBytes += 2;
7370b57cec5SDimitry Andric     }
7380b57cec5SDimitry Andric   } else if (CalleeMO.isGlobal()) {
7390b57cec5SDimitry Andric     const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT);
7400b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
7410b57cec5SDimitry Andric                                    .addReg(SystemZ::R14D)
7420b57cec5SDimitry Andric                                    .addExpr(Expr));
7430b57cec5SDimitry Andric     EncodedBytes += 6;
7440b57cec5SDimitry Andric   }
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric   // Emit padding.
7470b57cec5SDimitry Andric   unsigned NumBytes = Opers.getNumPatchBytes();
7480b57cec5SDimitry Andric   assert(NumBytes >= EncodedBytes &&
7490b57cec5SDimitry Andric          "Patchpoint can't request size less than the length of a call.");
7500b57cec5SDimitry Andric   assert((NumBytes - EncodedBytes) % 2 == 0 &&
7510b57cec5SDimitry Andric          "Invalid number of NOP bytes requested!");
7520b57cec5SDimitry Andric   while (EncodedBytes < NumBytes)
7530b57cec5SDimitry Andric     EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,
7540b57cec5SDimitry Andric                             getSubtargetInfo());
7550b57cec5SDimitry Andric }
7560b57cec5SDimitry Andric 
757*bdd1243dSDimitry Andric // The *alignment* of 128-bit vector types is different between the software
758*bdd1243dSDimitry Andric // and hardware vector ABIs. If the there is an externally visible use of a
759*bdd1243dSDimitry Andric // vector type in the module it should be annotated with an attribute.
760*bdd1243dSDimitry Andric void SystemZAsmPrinter::emitAttributes(Module &M) {
761*bdd1243dSDimitry Andric   if (M.getModuleFlag("s390x-visible-vector-ABI")) {
762*bdd1243dSDimitry Andric     bool HasVectorFeature =
763*bdd1243dSDimitry Andric       TM.getMCSubtargetInfo()->getFeatureBits()[SystemZ::FeatureVector];
764*bdd1243dSDimitry Andric     OutStreamer->emitGNUAttribute(8, HasVectorFeature ? 2 : 1);
765*bdd1243dSDimitry Andric   }
766*bdd1243dSDimitry Andric }
767*bdd1243dSDimitry Andric 
7680b57cec5SDimitry Andric // Convert a SystemZ-specific constant pool modifier into the associated
7690b57cec5SDimitry Andric // MCSymbolRefExpr variant kind.
7700b57cec5SDimitry Andric static MCSymbolRefExpr::VariantKind
7710b57cec5SDimitry Andric getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
7720b57cec5SDimitry Andric   switch (Modifier) {
7730b57cec5SDimitry Andric   case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
7740b57cec5SDimitry Andric   case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM;
7750b57cec5SDimitry Andric   case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF;
7760b57cec5SDimitry Andric   case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
7770b57cec5SDimitry Andric   }
7780b57cec5SDimitry Andric   llvm_unreachable("Invalid SystemCPModifier!");
7790b57cec5SDimitry Andric }
7800b57cec5SDimitry Andric 
7815ffd83dbSDimitry Andric void SystemZAsmPrinter::emitMachineConstantPoolValue(
7825ffd83dbSDimitry Andric     MachineConstantPoolValue *MCPV) {
7830b57cec5SDimitry Andric   auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
7840b57cec5SDimitry Andric 
7850b57cec5SDimitry Andric   const MCExpr *Expr =
7860b57cec5SDimitry Andric     MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()),
7870b57cec5SDimitry Andric                             getModifierVariantKind(ZCPV->getModifier()),
7880b57cec5SDimitry Andric                             OutContext);
7890b57cec5SDimitry Andric   uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
7900b57cec5SDimitry Andric 
7915ffd83dbSDimitry Andric   OutStreamer->emitValue(Expr, Size);
7920b57cec5SDimitry Andric }
7930b57cec5SDimitry Andric 
794*bdd1243dSDimitry Andric static void printFormattedRegName(const MCAsmInfo *MAI, unsigned RegNo,
795*bdd1243dSDimitry Andric                                   raw_ostream &OS) {
796*bdd1243dSDimitry Andric   const char *RegName = SystemZInstPrinter::getRegisterName(RegNo);
797*bdd1243dSDimitry Andric   if (MAI->getAssemblerDialect() == AD_HLASM) {
798*bdd1243dSDimitry Andric     // Skip register prefix so that only register number is left
799*bdd1243dSDimitry Andric     assert(isalpha(RegName[0]) && isdigit(RegName[1]));
800*bdd1243dSDimitry Andric     OS << (RegName + 1);
801*bdd1243dSDimitry Andric   } else
802*bdd1243dSDimitry Andric     OS << '%' << RegName;
803*bdd1243dSDimitry Andric }
804*bdd1243dSDimitry Andric 
805*bdd1243dSDimitry Andric static void printOperand(const MCOperand &MCOp, const MCAsmInfo *MAI,
806*bdd1243dSDimitry Andric                          raw_ostream &OS) {
807*bdd1243dSDimitry Andric   if (MCOp.isReg()) {
808*bdd1243dSDimitry Andric     if (!MCOp.getReg())
809*bdd1243dSDimitry Andric       OS << '0';
810*bdd1243dSDimitry Andric     else
811*bdd1243dSDimitry Andric       printFormattedRegName(MAI, MCOp.getReg(), OS);
812*bdd1243dSDimitry Andric   } else if (MCOp.isImm())
813*bdd1243dSDimitry Andric     OS << MCOp.getImm();
814*bdd1243dSDimitry Andric   else if (MCOp.isExpr())
815*bdd1243dSDimitry Andric     MCOp.getExpr()->print(OS, MAI);
816*bdd1243dSDimitry Andric   else
817*bdd1243dSDimitry Andric     llvm_unreachable("Invalid operand");
818*bdd1243dSDimitry Andric }
819*bdd1243dSDimitry Andric 
820*bdd1243dSDimitry Andric static void printAddress(const MCAsmInfo *MAI, unsigned Base,
821*bdd1243dSDimitry Andric                          const MCOperand &DispMO, unsigned Index,
822*bdd1243dSDimitry Andric                          raw_ostream &OS) {
823*bdd1243dSDimitry Andric   printOperand(DispMO, MAI, OS);
824*bdd1243dSDimitry Andric   if (Base || Index) {
825*bdd1243dSDimitry Andric     OS << '(';
826*bdd1243dSDimitry Andric     if (Index) {
827*bdd1243dSDimitry Andric       printFormattedRegName(MAI, Index, OS);
828*bdd1243dSDimitry Andric       if (Base)
829*bdd1243dSDimitry Andric         OS << ',';
830*bdd1243dSDimitry Andric     }
831*bdd1243dSDimitry Andric     if (Base)
832*bdd1243dSDimitry Andric       printFormattedRegName(MAI, Base, OS);
833*bdd1243dSDimitry Andric     OS << ')';
834*bdd1243dSDimitry Andric   }
835*bdd1243dSDimitry Andric }
836*bdd1243dSDimitry Andric 
8370b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
8380b57cec5SDimitry Andric                                         const char *ExtraCode,
8390b57cec5SDimitry Andric                                         raw_ostream &OS) {
840fe6060f1SDimitry Andric   const MCRegisterInfo &MRI = *TM.getMCRegisterInfo();
841fe6060f1SDimitry Andric   const MachineOperand &MO = MI->getOperand(OpNo);
842fe6060f1SDimitry Andric   MCOperand MCOp;
843fe6060f1SDimitry Andric   if (ExtraCode) {
844fe6060f1SDimitry Andric     if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() &&
845fe6060f1SDimitry Andric         SystemZ::GR128BitRegClass.contains(MO.getReg()))
846fe6060f1SDimitry Andric       MCOp =
847fe6060f1SDimitry Andric           MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64));
848fe6060f1SDimitry Andric     else
8490b57cec5SDimitry Andric       return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
850fe6060f1SDimitry Andric   } else {
8510b57cec5SDimitry Andric     SystemZMCInstLower Lower(MF->getContext(), *this);
852fe6060f1SDimitry Andric     MCOp = Lower.lowerOperand(MO);
853fe6060f1SDimitry Andric   }
854*bdd1243dSDimitry Andric   printOperand(MCOp, MAI, OS);
8550b57cec5SDimitry Andric   return false;
8560b57cec5SDimitry Andric }
8570b57cec5SDimitry Andric 
8580b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
8590b57cec5SDimitry Andric                                               unsigned OpNo,
8600b57cec5SDimitry Andric                                               const char *ExtraCode,
8610b57cec5SDimitry Andric                                               raw_ostream &OS) {
862349cc55cSDimitry Andric   printAddress(MAI, MI->getOperand(OpNo).getReg(),
863349cc55cSDimitry Andric                MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()),
8640b57cec5SDimitry Andric                MI->getOperand(OpNo + 2).getReg(), OS);
8650b57cec5SDimitry Andric   return false;
8660b57cec5SDimitry Andric }
8670b57cec5SDimitry Andric 
8685ffd83dbSDimitry Andric void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
869*bdd1243dSDimitry Andric   emitAttributes(M);
8700b57cec5SDimitry Andric }
8710b57cec5SDimitry Andric 
87281ad6265SDimitry Andric void SystemZAsmPrinter::emitFunctionBodyEnd() {
87381ad6265SDimitry Andric   if (TM.getTargetTriple().isOSzOS()) {
87481ad6265SDimitry Andric     // Emit symbol for the end of function if the z/OS target streamer
87581ad6265SDimitry Andric     // is used. This is needed to calculate the size of the function.
87681ad6265SDimitry Andric     MCSymbol *FnEndSym = createTempSymbol("func_end");
87781ad6265SDimitry Andric     OutStreamer->emitLabel(FnEndSym);
87881ad6265SDimitry Andric 
87981ad6265SDimitry Andric     OutStreamer->pushSection();
88081ad6265SDimitry Andric     OutStreamer->switchSection(getObjFileLowering().getPPA1Section());
88181ad6265SDimitry Andric     emitPPA1(FnEndSym);
88281ad6265SDimitry Andric     OutStreamer->popSection();
88381ad6265SDimitry Andric 
88481ad6265SDimitry Andric     CurrentFnPPA1Sym = nullptr;
88581ad6265SDimitry Andric     CurrentFnEPMarkerSym = nullptr;
88681ad6265SDimitry Andric   }
88781ad6265SDimitry Andric }
88881ad6265SDimitry Andric 
88981ad6265SDimitry Andric static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
89081ad6265SDimitry Andric                           bool StackProtector, bool FPRMask, bool VRMask) {
89181ad6265SDimitry Andric   enum class PPA1Flag1 : uint8_t {
89281ad6265SDimitry Andric     DSA64Bit = (0x80 >> 0),
89381ad6265SDimitry Andric     VarArg = (0x80 >> 7),
89481ad6265SDimitry Andric     LLVM_MARK_AS_BITMASK_ENUM(DSA64Bit)
89581ad6265SDimitry Andric   };
89681ad6265SDimitry Andric   enum class PPA1Flag2 : uint8_t {
89781ad6265SDimitry Andric     ExternalProcedure = (0x80 >> 0),
89881ad6265SDimitry Andric     STACKPROTECTOR = (0x80 >> 3),
89981ad6265SDimitry Andric     LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure)
90081ad6265SDimitry Andric   };
90181ad6265SDimitry Andric   enum class PPA1Flag3 : uint8_t {
90281ad6265SDimitry Andric     FPRMask = (0x80 >> 2),
90381ad6265SDimitry Andric     LLVM_MARK_AS_BITMASK_ENUM(FPRMask)
90481ad6265SDimitry Andric   };
90581ad6265SDimitry Andric   enum class PPA1Flag4 : uint8_t {
90681ad6265SDimitry Andric     EPMOffsetPresent = (0x80 >> 0),
90781ad6265SDimitry Andric     VRMask = (0x80 >> 2),
90881ad6265SDimitry Andric     ProcedureNamePresent = (0x80 >> 7),
90981ad6265SDimitry Andric     LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent)
91081ad6265SDimitry Andric   };
91181ad6265SDimitry Andric 
91281ad6265SDimitry Andric   // Declare optional section flags that can be modified.
91381ad6265SDimitry Andric   auto Flags1 = PPA1Flag1(0);
91481ad6265SDimitry Andric   auto Flags2 = PPA1Flag2::ExternalProcedure;
91581ad6265SDimitry Andric   auto Flags3 = PPA1Flag3(0);
91681ad6265SDimitry Andric   auto Flags4 = PPA1Flag4::EPMOffsetPresent | PPA1Flag4::ProcedureNamePresent;
91781ad6265SDimitry Andric 
91881ad6265SDimitry Andric   Flags1 |= PPA1Flag1::DSA64Bit;
91981ad6265SDimitry Andric 
92081ad6265SDimitry Andric   if (VarArg)
92181ad6265SDimitry Andric     Flags1 |= PPA1Flag1::VarArg;
92281ad6265SDimitry Andric 
92381ad6265SDimitry Andric   if (StackProtector)
92481ad6265SDimitry Andric     Flags2 |= PPA1Flag2::STACKPROTECTOR;
92581ad6265SDimitry Andric 
92681ad6265SDimitry Andric   // SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in.
92781ad6265SDimitry Andric   if (FPRMask)
92881ad6265SDimitry Andric     Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag.
92981ad6265SDimitry Andric 
93081ad6265SDimitry Andric   if (VRMask)
93181ad6265SDimitry Andric     Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag.
93281ad6265SDimitry Andric 
93381ad6265SDimitry Andric   OutStreamer->AddComment("PPA1 Flags 1");
93481ad6265SDimitry Andric   if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit)
93581ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 0: 1 = 64-bit DSA");
93681ad6265SDimitry Andric   else
93781ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 0: 0 = 32-bit DSA");
93881ad6265SDimitry Andric   if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg)
93981ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 7: 1 = Vararg function");
94081ad6265SDimitry Andric   OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1.
94181ad6265SDimitry Andric 
94281ad6265SDimitry Andric   OutStreamer->AddComment("PPA1 Flags 2");
94381ad6265SDimitry Andric   if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure)
94481ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 0: 1 = External procedure");
94581ad6265SDimitry Andric   if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR)
94681ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 3: 1 = STACKPROTECT is enabled");
94781ad6265SDimitry Andric   else
94881ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 3: 0 = STACKPROTECT is not enabled");
94981ad6265SDimitry Andric   OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2.
95081ad6265SDimitry Andric 
95181ad6265SDimitry Andric   OutStreamer->AddComment("PPA1 Flags 3");
95281ad6265SDimitry Andric   if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask)
95381ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 2: 1 = FP Reg Mask is in optional area");
95481ad6265SDimitry Andric   OutStreamer->emitInt8(
95581ad6265SDimitry Andric       static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections).
95681ad6265SDimitry Andric 
95781ad6265SDimitry Andric   OutStreamer->AddComment("PPA1 Flags 4");
95881ad6265SDimitry Andric   if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask)
95981ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 2: 1 = Vector Reg Mask is in optional area");
96081ad6265SDimitry Andric   OutStreamer->emitInt8(static_cast<uint8_t>(
96181ad6265SDimitry Andric       Flags4)); // Flags 4 (optional sections, always emit these).
96281ad6265SDimitry Andric }
96381ad6265SDimitry Andric 
96481ad6265SDimitry Andric void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
96581ad6265SDimitry Andric   const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
96681ad6265SDimitry Andric   const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
96781ad6265SDimitry Andric   const auto TargetHasVector = Subtarget.hasVector();
96881ad6265SDimitry Andric 
96981ad6265SDimitry Andric   const SystemZMachineFunctionInfo *ZFI =
97081ad6265SDimitry Andric       MF->getInfo<SystemZMachineFunctionInfo>();
97181ad6265SDimitry Andric   const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>(
97281ad6265SDimitry Andric       Subtarget.getFrameLowering());
97381ad6265SDimitry Andric   const MachineFrameInfo &MFFrame = MF->getFrameInfo();
97481ad6265SDimitry Andric 
97581ad6265SDimitry Andric   // Get saved GPR/FPR/VPR masks.
97681ad6265SDimitry Andric   const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();
97781ad6265SDimitry Andric   uint16_t SavedGPRMask = 0;
97881ad6265SDimitry Andric   uint16_t SavedFPRMask = 0;
97981ad6265SDimitry Andric   uint8_t SavedVRMask = 0;
98081ad6265SDimitry Andric   int64_t OffsetFPR = 0;
98181ad6265SDimitry Andric   int64_t OffsetVR = 0;
98281ad6265SDimitry Andric   const int64_t TopOfStack =
98381ad6265SDimitry Andric       MFFrame.getOffsetAdjustment() + MFFrame.getStackSize();
98481ad6265SDimitry Andric 
98581ad6265SDimitry Andric   // Loop over the spilled registers. The CalleeSavedInfo can't be used because
98681ad6265SDimitry Andric   // it does not contain all spilled registers.
98781ad6265SDimitry Andric   for (unsigned I = ZFI->getSpillGPRRegs().LowGPR,
98881ad6265SDimitry Andric                 E = ZFI->getSpillGPRRegs().HighGPR;
98981ad6265SDimitry Andric        I && E && I <= E; ++I) {
99081ad6265SDimitry Andric     unsigned V = TRI->getEncodingValue((Register)I);
99181ad6265SDimitry Andric     assert(V < 16 && "GPR index out of range");
99281ad6265SDimitry Andric     SavedGPRMask |= 1 << (15 - V);
99381ad6265SDimitry Andric   }
99481ad6265SDimitry Andric 
99581ad6265SDimitry Andric   for (auto &CS : CSI) {
99681ad6265SDimitry Andric     unsigned Reg = CS.getReg();
99781ad6265SDimitry Andric     unsigned I = TRI->getEncodingValue(Reg);
99881ad6265SDimitry Andric 
99981ad6265SDimitry Andric     if (SystemZ::FP64BitRegClass.contains(Reg)) {
100081ad6265SDimitry Andric       assert(I < 16 && "FPR index out of range");
100181ad6265SDimitry Andric       SavedFPRMask |= 1 << (15 - I);
100281ad6265SDimitry Andric       int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
100381ad6265SDimitry Andric       if (Temp < OffsetFPR)
100481ad6265SDimitry Andric         OffsetFPR = Temp;
100581ad6265SDimitry Andric     } else if (SystemZ::VR128BitRegClass.contains(Reg)) {
100681ad6265SDimitry Andric       assert(I >= 16 && I <= 23 && "VPR index out of range");
100781ad6265SDimitry Andric       unsigned BitNum = I - 16;
100881ad6265SDimitry Andric       SavedVRMask |= 1 << (7 - BitNum);
100981ad6265SDimitry Andric       int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
101081ad6265SDimitry Andric       if (Temp < OffsetVR)
101181ad6265SDimitry Andric         OffsetVR = Temp;
101281ad6265SDimitry Andric     }
101381ad6265SDimitry Andric   }
101481ad6265SDimitry Andric 
101581ad6265SDimitry Andric   // Adjust the offset.
101681ad6265SDimitry Andric   OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0;
101781ad6265SDimitry Andric   OffsetVR += (OffsetVR < 0) ? TopOfStack : 0;
101881ad6265SDimitry Andric 
101981ad6265SDimitry Andric   // Get alloca register.
102081ad6265SDimitry Andric   uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF));
102181ad6265SDimitry Andric   uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0;
102281ad6265SDimitry Andric   assert(AllocaReg < 16 && "Can't have alloca register larger than 15");
102381ad6265SDimitry Andric   (void)AllocaReg;
102481ad6265SDimitry Andric 
102581ad6265SDimitry Andric   // Build FPR save area offset.
102681ad6265SDimitry Andric   uint32_t FrameAndFPROffset = 0;
102781ad6265SDimitry Andric   if (SavedFPRMask) {
102881ad6265SDimitry Andric     uint64_t FPRSaveAreaOffset = OffsetFPR;
102981ad6265SDimitry Andric     assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range");
103081ad6265SDimitry Andric 
103181ad6265SDimitry Andric     FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
103281ad6265SDimitry Andric     FrameAndFPROffset |= FrameReg << 28;                // Put into top 4 bits.
103381ad6265SDimitry Andric   }
103481ad6265SDimitry Andric 
103581ad6265SDimitry Andric   // Build VR save area offset.
103681ad6265SDimitry Andric   uint32_t FrameAndVROffset = 0;
103781ad6265SDimitry Andric   if (TargetHasVector && SavedVRMask) {
103881ad6265SDimitry Andric     uint64_t VRSaveAreaOffset = OffsetVR;
103981ad6265SDimitry Andric     assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range");
104081ad6265SDimitry Andric 
104181ad6265SDimitry Andric     FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
104281ad6265SDimitry Andric     FrameAndVROffset |= FrameReg << 28;               // Put into top 4 bits.
104381ad6265SDimitry Andric   }
104481ad6265SDimitry Andric 
104581ad6265SDimitry Andric   // Emit PPA1 section.
104681ad6265SDimitry Andric   OutStreamer->AddComment("PPA1");
104781ad6265SDimitry Andric   OutStreamer->emitLabel(CurrentFnPPA1Sym);
104881ad6265SDimitry Andric   OutStreamer->AddComment("Version");
104981ad6265SDimitry Andric   OutStreamer->emitInt8(0x02); // Version.
105081ad6265SDimitry Andric   OutStreamer->AddComment("LE Signature X'CE'");
105181ad6265SDimitry Andric   OutStreamer->emitInt8(0xCE); // CEL signature.
105281ad6265SDimitry Andric   OutStreamer->AddComment("Saved GPR Mask");
105381ad6265SDimitry Andric   OutStreamer->emitInt16(SavedGPRMask);
105481ad6265SDimitry Andric 
105581ad6265SDimitry Andric   emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(),
105681ad6265SDimitry Andric                 MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0,
105781ad6265SDimitry Andric                 TargetHasVector && SavedVRMask != 0);
105881ad6265SDimitry Andric 
105981ad6265SDimitry Andric   OutStreamer->AddComment("Length/4 of Parms");
106081ad6265SDimitry Andric   OutStreamer->emitInt16(
106181ad6265SDimitry Andric       static_cast<uint16_t>(MFFrame.getMaxCallFrameSize() / 4)); // Parms/4.
106281ad6265SDimitry Andric   OutStreamer->AddComment("Length of Code");
106381ad6265SDimitry Andric   OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4);
106481ad6265SDimitry Andric 
106581ad6265SDimitry Andric   // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3).
106681ad6265SDimitry Andric   if (SavedFPRMask) {
106781ad6265SDimitry Andric     OutStreamer->AddComment("FPR mask");
106881ad6265SDimitry Andric     OutStreamer->emitInt16(SavedFPRMask);
106981ad6265SDimitry Andric     OutStreamer->AddComment("AR mask");
107081ad6265SDimitry Andric     OutStreamer->emitInt16(0); // AR Mask, unused currently.
107181ad6265SDimitry Andric     OutStreamer->AddComment("FPR Save Area Locator");
107281ad6265SDimitry Andric     OutStreamer->AddComment(Twine("  Bit 0-3: Register R")
107381ad6265SDimitry Andric                                 .concat(utostr(FrameAndFPROffset >> 28))
107481ad6265SDimitry Andric                                 .str());
107581ad6265SDimitry Andric     OutStreamer->AddComment(Twine("  Bit 4-31: Offset ")
107681ad6265SDimitry Andric                                 .concat(utostr(FrameAndFPROffset & 0x0FFFFFFF))
107781ad6265SDimitry Andric                                 .str());
107881ad6265SDimitry Andric     OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with
107981ad6265SDimitry Andric                                                // register to add value to
108081ad6265SDimitry Andric                                                // (alloca reg).
108181ad6265SDimitry Andric   }
108281ad6265SDimitry Andric 
108381ad6265SDimitry Andric   // Emit saved VR mask to VR save area.
108481ad6265SDimitry Andric   if (TargetHasVector && SavedVRMask) {
108581ad6265SDimitry Andric     OutStreamer->AddComment("VR mask");
108681ad6265SDimitry Andric     OutStreamer->emitInt8(SavedVRMask);
108781ad6265SDimitry Andric     OutStreamer->emitInt8(0);  // Reserved.
108881ad6265SDimitry Andric     OutStreamer->emitInt16(0); // Also reserved.
108981ad6265SDimitry Andric     OutStreamer->AddComment("VR Save Area Locator");
109081ad6265SDimitry Andric     OutStreamer->AddComment(Twine("  Bit 0-3: Register R")
109181ad6265SDimitry Andric                                 .concat(utostr(FrameAndVROffset >> 28))
109281ad6265SDimitry Andric                                 .str());
109381ad6265SDimitry Andric     OutStreamer->AddComment(Twine("  Bit 4-31: Offset ")
109481ad6265SDimitry Andric                                 .concat(utostr(FrameAndVROffset & 0x0FFFFFFF))
109581ad6265SDimitry Andric                                 .str());
109681ad6265SDimitry Andric     OutStreamer->emitInt32(FrameAndVROffset);
109781ad6265SDimitry Andric   }
109881ad6265SDimitry Andric 
109981ad6265SDimitry Andric   // Emit offset to entry point optional section (0x80 of flags 4).
110081ad6265SDimitry Andric   OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym,
110181ad6265SDimitry Andric                                       4);
110281ad6265SDimitry Andric }
110381ad6265SDimitry Andric 
110404eeddc0SDimitry Andric void SystemZAsmPrinter::emitFunctionEntryLabel() {
110581ad6265SDimitry Andric   const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
110604eeddc0SDimitry Andric 
110704eeddc0SDimitry Andric   if (Subtarget.getTargetTriple().isOSzOS()) {
110804eeddc0SDimitry Andric     MCContext &OutContext = OutStreamer->getContext();
110981ad6265SDimitry Andric 
111081ad6265SDimitry Andric     // Save information for later use.
111181ad6265SDimitry Andric     std::string N(MF->getFunction().hasName()
111281ad6265SDimitry Andric                       ? Twine(MF->getFunction().getName()).concat("_").str()
111381ad6265SDimitry Andric                       : "");
111481ad6265SDimitry Andric 
111581ad6265SDimitry Andric     CurrentFnEPMarkerSym =
111681ad6265SDimitry Andric         OutContext.createTempSymbol(Twine("EPM_").concat(N).str(), true);
111781ad6265SDimitry Andric     CurrentFnPPA1Sym =
111881ad6265SDimitry Andric         OutContext.createTempSymbol(Twine("PPA1_").concat(N).str(), true);
111904eeddc0SDimitry Andric 
112004eeddc0SDimitry Andric     // EntryPoint Marker
112104eeddc0SDimitry Andric     const MachineFrameInfo &MFFrame = MF->getFrameInfo();
112204eeddc0SDimitry Andric     bool IsUsingAlloca = MFFrame.hasVarSizedObjects();
112304eeddc0SDimitry Andric 
112404eeddc0SDimitry Andric     // Set Flags
112504eeddc0SDimitry Andric     uint8_t Flags = 0;
112604eeddc0SDimitry Andric     if (IsUsingAlloca)
112704eeddc0SDimitry Andric       Flags |= 0x04;
112804eeddc0SDimitry Andric 
112904eeddc0SDimitry Andric     uint32_t DSASize = MFFrame.getStackSize();
113004eeddc0SDimitry Andric 
113104eeddc0SDimitry Andric     // Combine into top 27 bits of DSASize and bottom 5 bits of Flags.
113204eeddc0SDimitry Andric     uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5
113304eeddc0SDimitry Andric     DSAAndFlags |= Flags;
113404eeddc0SDimitry Andric 
113504eeddc0SDimitry Andric     // Emit entry point marker section.
113604eeddc0SDimitry Andric     OutStreamer->AddComment("XPLINK Routine Layout Entry");
113781ad6265SDimitry Andric     OutStreamer->emitLabel(CurrentFnEPMarkerSym);
113804eeddc0SDimitry Andric     OutStreamer->AddComment("Eyecatcher 0x00C300C500C500");
113904eeddc0SDimitry Andric     OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher.
114004eeddc0SDimitry Andric     OutStreamer->AddComment("Mark Type C'1'");
114104eeddc0SDimitry Andric     OutStreamer->emitInt8(0xF1); // Mark Type.
114281ad6265SDimitry Andric     OutStreamer->AddComment("Offset to PPA1");
114381ad6265SDimitry Andric     OutStreamer->emitAbsoluteSymbolDiff(CurrentFnPPA1Sym, CurrentFnEPMarkerSym,
114481ad6265SDimitry Andric                                         4);
114504eeddc0SDimitry Andric     if (OutStreamer->isVerboseAsm()) {
114604eeddc0SDimitry Andric       OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
114704eeddc0SDimitry Andric       OutStreamer->AddComment("Entry Flags");
114804eeddc0SDimitry Andric       if (Flags & 0x04)
114904eeddc0SDimitry Andric         OutStreamer->AddComment("  Bit 2: 1 = Uses alloca");
115004eeddc0SDimitry Andric       else
115104eeddc0SDimitry Andric         OutStreamer->AddComment("  Bit 2: 0 = Does not use alloca");
115204eeddc0SDimitry Andric     }
115304eeddc0SDimitry Andric     OutStreamer->emitInt32(DSAAndFlags);
115404eeddc0SDimitry Andric   }
115504eeddc0SDimitry Andric 
115604eeddc0SDimitry Andric   AsmPrinter::emitFunctionEntryLabel();
115704eeddc0SDimitry Andric }
115804eeddc0SDimitry Andric 
11590b57cec5SDimitry Andric // Force static initialization.
1160480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() {
11610b57cec5SDimitry Andric   RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget());
11620b57cec5SDimitry Andric }
1163