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