15f613dfdSUlrich Weigand //===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===//
25f613dfdSUlrich Weigand //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65f613dfdSUlrich Weigand //
75f613dfdSUlrich Weigand //===----------------------------------------------------------------------===//
85f613dfdSUlrich Weigand //
95f613dfdSUlrich Weigand // Streams SystemZ assembly language and associated data, in the form of
105f613dfdSUlrich Weigand // MCInsts and MCExprs respectively.
115f613dfdSUlrich Weigand //
125f613dfdSUlrich Weigand //===----------------------------------------------------------------------===//
135f613dfdSUlrich Weigand 
145f613dfdSUlrich Weigand #include "SystemZAsmPrinter.h"
15d0124bd7SRichard Trieu #include "MCTargetDesc/SystemZInstPrinter.h"
165f613dfdSUlrich Weigand #include "SystemZConstantPoolValue.h"
175f613dfdSUlrich Weigand #include "SystemZMCInstLower.h"
181e6f98b8SRichard Trieu #include "TargetInfo/SystemZTargetInfo.h"
196be15788SJonas Paulsson #include "llvm/BinaryFormat/ELF.h"
205f613dfdSUlrich Weigand #include "llvm/CodeGen/MachineModuleInfoImpls.h"
215f613dfdSUlrich Weigand #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
22894843cbSRafael Espindola #include "llvm/IR/Mangler.h"
235f613dfdSUlrich Weigand #include "llvm/MC/MCExpr.h"
249ab97cd1SRichard Sandiford #include "llvm/MC/MCInstBuilder.h"
256be15788SJonas Paulsson #include "llvm/MC/MCSectionELF.h"
265f613dfdSUlrich Weigand #include "llvm/MC/MCStreamer.h"
2789b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
285f613dfdSUlrich Weigand 
295f613dfdSUlrich Weigand using namespace llvm;
305f613dfdSUlrich Weigand 
31652784e2SRichard Sandiford // Return an RI instruction like MI with opcode Opcode, but with the
32652784e2SRichard Sandiford // GR64 register operands turned into GR32s.
lowerRILow(const MachineInstr * MI,unsigned Opcode)33652784e2SRichard Sandiford static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {
34f03789caSRichard Sandiford   if (MI->isCompare())
35f03789caSRichard Sandiford     return MCInstBuilder(Opcode)
36f03789caSRichard Sandiford       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
37f03789caSRichard Sandiford       .addImm(MI->getOperand(1).getImm());
38f03789caSRichard Sandiford   else
39652784e2SRichard Sandiford     return MCInstBuilder(Opcode)
40652784e2SRichard Sandiford       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
41652784e2SRichard Sandiford       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg()))
42652784e2SRichard Sandiford       .addImm(MI->getOperand(2).getImm());
43652784e2SRichard Sandiford }
44652784e2SRichard Sandiford 
450755c93bSRichard Sandiford // Return an RI instruction like MI with opcode Opcode, but with the
461a56931bSRichard Sandiford // GR64 register operands turned into GRH32s.
lowerRIHigh(const MachineInstr * MI,unsigned Opcode)471a56931bSRichard Sandiford static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) {
48f03789caSRichard Sandiford   if (MI->isCompare())
49f03789caSRichard Sandiford     return MCInstBuilder(Opcode)
50f03789caSRichard Sandiford       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
51f03789caSRichard Sandiford       .addImm(MI->getOperand(1).getImm());
52f03789caSRichard Sandiford   else
531a56931bSRichard Sandiford     return MCInstBuilder(Opcode)
541a56931bSRichard Sandiford       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
551a56931bSRichard Sandiford       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg()))
561a56931bSRichard Sandiford       .addImm(MI->getOperand(2).getImm());
571a56931bSRichard Sandiford }
581a56931bSRichard Sandiford 
591a56931bSRichard Sandiford // Return an RI instruction like MI with opcode Opcode, but with the
600755c93bSRichard Sandiford // R2 register turned into a GR64.
lowerRIEfLow(const MachineInstr * MI,unsigned Opcode)610755c93bSRichard Sandiford static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {
620755c93bSRichard Sandiford   return MCInstBuilder(Opcode)
630755c93bSRichard Sandiford     .addReg(MI->getOperand(0).getReg())
640755c93bSRichard Sandiford     .addReg(MI->getOperand(1).getReg())
650755c93bSRichard Sandiford     .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()))
660755c93bSRichard Sandiford     .addImm(MI->getOperand(3).getImm())
670755c93bSRichard Sandiford     .addImm(MI->getOperand(4).getImm())
680755c93bSRichard Sandiford     .addImm(MI->getOperand(5).getImm());
690755c93bSRichard Sandiford }
700755c93bSRichard Sandiford 
getTLSGetOffset(MCContext & Context)717db6918eSUlrich Weigand static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
727db6918eSUlrich Weigand   StringRef Name = "__tls_get_offset";
7313760bd1SJim Grosbach   return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
747db6918eSUlrich Weigand                                  MCSymbolRefExpr::VK_PLT,
757db6918eSUlrich Weigand                                  Context);
767db6918eSUlrich Weigand }
777db6918eSUlrich Weigand 
getGlobalOffsetTable(MCContext & Context)787db6918eSUlrich Weigand static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) {
797db6918eSUlrich Weigand   StringRef Name = "_GLOBAL_OFFSET_TABLE_";
8013760bd1SJim Grosbach   return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
817db6918eSUlrich Weigand                                  MCSymbolRefExpr::VK_None,
827db6918eSUlrich Weigand                                  Context);
837db6918eSUlrich Weigand }
847db6918eSUlrich Weigand 
853641b10fSUlrich Weigand // MI is an instruction that accepts an optional alignment hint,
863641b10fSUlrich Weigand // and which was already lowered to LoweredMI.  If the alignment
873641b10fSUlrich Weigand // of the original memory operand is known, update LoweredMI to
883641b10fSUlrich Weigand // an instruction with the corresponding hint set.
lowerAlignmentHint(const MachineInstr * MI,MCInst & LoweredMI,unsigned Opcode)893641b10fSUlrich Weigand static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI,
903641b10fSUlrich Weigand                                unsigned Opcode) {
91cf426100SJonas Paulsson   if (MI->memoperands_empty())
923641b10fSUlrich Weigand     return;
93cf426100SJonas Paulsson 
94cf426100SJonas Paulsson   Align Alignment = Align(16);
95cf426100SJonas Paulsson   for (MachineInstr::mmo_iterator MMOI = MI->memoperands_begin(),
96cf426100SJonas Paulsson          EE = MI->memoperands_end(); MMOI != EE; ++MMOI)
97cf426100SJonas Paulsson     if ((*MMOI)->getAlign() < Alignment)
98cf426100SJonas Paulsson       Alignment = (*MMOI)->getAlign();
99cf426100SJonas Paulsson 
1003641b10fSUlrich Weigand   unsigned AlignmentHint = 0;
101cf426100SJonas Paulsson   if (Alignment >= Align(16))
1023641b10fSUlrich Weigand     AlignmentHint = 4;
103cf426100SJonas Paulsson   else if (Alignment >= Align(8))
1043641b10fSUlrich Weigand     AlignmentHint = 3;
1053641b10fSUlrich Weigand   if (AlignmentHint == 0)
1063641b10fSUlrich Weigand     return;
1073641b10fSUlrich Weigand 
1083641b10fSUlrich Weigand   LoweredMI.setOpcode(Opcode);
1093641b10fSUlrich Weigand   LoweredMI.addOperand(MCOperand::createImm(AlignmentHint));
1103641b10fSUlrich Weigand }
1113641b10fSUlrich Weigand 
11249506d78SUlrich Weigand // MI loads the high part of a vector from memory.  Return an instruction
11349506d78SUlrich Weigand // that uses replicating vector load Opcode to do the same thing.
lowerSubvectorLoad(const MachineInstr * MI,unsigned Opcode)11449506d78SUlrich Weigand static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) {
11549506d78SUlrich Weigand   return MCInstBuilder(Opcode)
11649506d78SUlrich Weigand     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
11749506d78SUlrich Weigand     .addReg(MI->getOperand(1).getReg())
11849506d78SUlrich Weigand     .addImm(MI->getOperand(2).getImm())
11949506d78SUlrich Weigand     .addReg(MI->getOperand(3).getReg());
12049506d78SUlrich Weigand }
12149506d78SUlrich Weigand 
12249506d78SUlrich Weigand // MI stores the high part of a vector to memory.  Return an instruction
12349506d78SUlrich Weigand // that uses elemental vector store Opcode to do the same thing.
lowerSubvectorStore(const MachineInstr * MI,unsigned Opcode)12449506d78SUlrich Weigand static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {
12549506d78SUlrich Weigand   return MCInstBuilder(Opcode)
12649506d78SUlrich Weigand     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
12749506d78SUlrich Weigand     .addReg(MI->getOperand(1).getReg())
12849506d78SUlrich Weigand     .addImm(MI->getOperand(2).getImm())
12949506d78SUlrich Weigand     .addReg(MI->getOperand(3).getReg())
13049506d78SUlrich Weigand     .addImm(0);
13149506d78SUlrich Weigand }
13249506d78SUlrich Weigand 
13362ba528aSKai Nacke // The XPLINK ABI requires that a no-op encoding the call type is emitted after
13462ba528aSKai Nacke // each call to a subroutine. This information can be used by the called
13562ba528aSKai Nacke // function to determine its entry point, e.g. for generating a backtrace. The
13662ba528aSKai Nacke // call type is encoded as a register number in the bcr instruction. See
13762ba528aSKai Nacke // enumeration CallType for the possible values.
emitCallInformation(CallType CT)13862ba528aSKai Nacke void SystemZAsmPrinter::emitCallInformation(CallType CT) {
13962ba528aSKai Nacke   EmitToStreamer(*OutStreamer,
14062ba528aSKai Nacke                  MCInstBuilder(SystemZ::BCRAsm)
14162ba528aSKai Nacke                      .addImm(0)
14262ba528aSKai Nacke                      .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)]));
14362ba528aSKai Nacke }
14462ba528aSKai Nacke 
emitInstruction(const MachineInstr * MI)145bcd24b2dSFangrui Song void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
146*3e0bf1c7SDavid Green   SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(),
147*3e0bf1c7SDavid Green                                           getSubtargetInfo().getFeatureBits());
148*3e0bf1c7SDavid Green 
14969c1d631SRafael Espindola   SystemZMCInstLower Lower(MF->getContext(), *this);
1505f613dfdSUlrich Weigand   MCInst LoweredMI;
1519ab97cd1SRichard Sandiford   switch (MI->getOpcode()) {
1529ab97cd1SRichard Sandiford   case SystemZ::Return:
153ff99f3a5SKai Nacke     LoweredMI = MCInstBuilder(SystemZ::BR)
154ff99f3a5SKai Nacke       .addReg(SystemZ::R14D);
155ff99f3a5SKai Nacke     break;
156ff99f3a5SKai Nacke 
157ff99f3a5SKai Nacke   case SystemZ::Return_XPLINK:
158ff99f3a5SKai Nacke     LoweredMI = MCInstBuilder(SystemZ::B)
159ff99f3a5SKai Nacke       .addReg(SystemZ::R7D)
160ff99f3a5SKai Nacke       .addImm(2)
161ff99f3a5SKai Nacke       .addReg(0);
1629ab97cd1SRichard Sandiford     break;
1639ab97cd1SRichard Sandiford 
1642eb027d2SUlrich Weigand   case SystemZ::CondReturn:
1652eb027d2SUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::BCR)
1662eb027d2SUlrich Weigand       .addImm(MI->getOperand(0).getImm())
1672eb027d2SUlrich Weigand       .addImm(MI->getOperand(1).getImm())
1682eb027d2SUlrich Weigand       .addReg(SystemZ::R14D);
1692eb027d2SUlrich Weigand     break;
1702eb027d2SUlrich Weigand 
171ff99f3a5SKai Nacke   case SystemZ::CondReturn_XPLINK:
172ff99f3a5SKai Nacke     LoweredMI = MCInstBuilder(SystemZ::BC)
173ff99f3a5SKai Nacke       .addImm(MI->getOperand(0).getImm())
174ff99f3a5SKai Nacke       .addImm(MI->getOperand(1).getImm())
175ff99f3a5SKai Nacke       .addReg(SystemZ::R7D)
176ff99f3a5SKai Nacke       .addImm(2)
177ff99f3a5SKai Nacke       .addReg(0);
178ff99f3a5SKai Nacke     break;
179ff99f3a5SKai Nacke 
1802eb027d2SUlrich Weigand   case SystemZ::CRBReturn:
1812eb027d2SUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::CRB)
1822eb027d2SUlrich Weigand       .addReg(MI->getOperand(0).getReg())
1832eb027d2SUlrich Weigand       .addReg(MI->getOperand(1).getReg())
1842eb027d2SUlrich Weigand       .addImm(MI->getOperand(2).getImm())
1852eb027d2SUlrich Weigand       .addReg(SystemZ::R14D)
1862eb027d2SUlrich Weigand       .addImm(0);
1872eb027d2SUlrich Weigand     break;
1882eb027d2SUlrich Weigand 
1892eb027d2SUlrich Weigand   case SystemZ::CGRBReturn:
1902eb027d2SUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::CGRB)
1912eb027d2SUlrich Weigand       .addReg(MI->getOperand(0).getReg())
1922eb027d2SUlrich Weigand       .addReg(MI->getOperand(1).getReg())
1932eb027d2SUlrich Weigand       .addImm(MI->getOperand(2).getImm())
1942eb027d2SUlrich Weigand       .addReg(SystemZ::R14D)
1952eb027d2SUlrich Weigand       .addImm(0);
1962eb027d2SUlrich Weigand     break;
1972eb027d2SUlrich Weigand 
1982eb027d2SUlrich Weigand   case SystemZ::CIBReturn:
1992eb027d2SUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::CIB)
2002eb027d2SUlrich Weigand       .addReg(MI->getOperand(0).getReg())
2012eb027d2SUlrich Weigand       .addImm(MI->getOperand(1).getImm())
2022eb027d2SUlrich Weigand       .addImm(MI->getOperand(2).getImm())
2032eb027d2SUlrich Weigand       .addReg(SystemZ::R14D)
2042eb027d2SUlrich Weigand       .addImm(0);
2052eb027d2SUlrich Weigand     break;
2062eb027d2SUlrich Weigand 
2072eb027d2SUlrich Weigand   case SystemZ::CGIBReturn:
2082eb027d2SUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::CGIB)
2092eb027d2SUlrich Weigand       .addReg(MI->getOperand(0).getReg())
2102eb027d2SUlrich Weigand       .addImm(MI->getOperand(1).getImm())
2112eb027d2SUlrich Weigand       .addImm(MI->getOperand(2).getImm())
2122eb027d2SUlrich Weigand       .addReg(SystemZ::R14D)
2132eb027d2SUlrich Weigand       .addImm(0);
2142eb027d2SUlrich Weigand     break;
2152eb027d2SUlrich Weigand 
2162eb027d2SUlrich Weigand   case SystemZ::CLRBReturn:
2172eb027d2SUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::CLRB)
2182eb027d2SUlrich Weigand       .addReg(MI->getOperand(0).getReg())
2192eb027d2SUlrich Weigand       .addReg(MI->getOperand(1).getReg())
2202eb027d2SUlrich Weigand       .addImm(MI->getOperand(2).getImm())
2212eb027d2SUlrich Weigand       .addReg(SystemZ::R14D)
2222eb027d2SUlrich Weigand       .addImm(0);
2232eb027d2SUlrich Weigand     break;
2242eb027d2SUlrich Weigand 
2252eb027d2SUlrich Weigand   case SystemZ::CLGRBReturn:
2262eb027d2SUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
2272eb027d2SUlrich Weigand       .addReg(MI->getOperand(0).getReg())
2282eb027d2SUlrich Weigand       .addReg(MI->getOperand(1).getReg())
2292eb027d2SUlrich Weigand       .addImm(MI->getOperand(2).getImm())
2302eb027d2SUlrich Weigand       .addReg(SystemZ::R14D)
2312eb027d2SUlrich Weigand       .addImm(0);
2322eb027d2SUlrich Weigand     break;
2332eb027d2SUlrich Weigand 
2342eb027d2SUlrich Weigand   case SystemZ::CLIBReturn:
2352eb027d2SUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::CLIB)
2362eb027d2SUlrich Weigand       .addReg(MI->getOperand(0).getReg())
2372eb027d2SUlrich Weigand       .addImm(MI->getOperand(1).getImm())
2382eb027d2SUlrich Weigand       .addImm(MI->getOperand(2).getImm())
2392eb027d2SUlrich Weigand       .addReg(SystemZ::R14D)
2402eb027d2SUlrich Weigand       .addImm(0);
2412eb027d2SUlrich Weigand     break;
2422eb027d2SUlrich Weigand 
2432eb027d2SUlrich Weigand   case SystemZ::CLGIBReturn:
2442eb027d2SUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
2452eb027d2SUlrich Weigand       .addReg(MI->getOperand(0).getReg())
2462eb027d2SUlrich Weigand       .addImm(MI->getOperand(1).getImm())
2472eb027d2SUlrich Weigand       .addImm(MI->getOperand(2).getImm())
2482eb027d2SUlrich Weigand       .addReg(SystemZ::R14D)
2492eb027d2SUlrich Weigand       .addImm(0);
2502eb027d2SUlrich Weigand     break;
2512eb027d2SUlrich Weigand 
252b006f555SYusra Syeda   case SystemZ::CallBRASL_XPLINK64:
253b006f555SYusra Syeda     EmitToStreamer(*OutStreamer,
254b006f555SYusra Syeda                    MCInstBuilder(SystemZ::BRASL)
255b006f555SYusra Syeda                        .addReg(SystemZ::R7D)
256b006f555SYusra Syeda                        .addExpr(Lower.getExpr(MI->getOperand(0),
257b006f555SYusra Syeda                                               MCSymbolRefExpr::VK_PLT)));
25862ba528aSKai Nacke     emitCallInformation(CallType::BRASL7);
259b006f555SYusra Syeda     return;
260b006f555SYusra Syeda 
261b006f555SYusra Syeda   case SystemZ::CallBASR_XPLINK64:
262b006f555SYusra Syeda     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
263b006f555SYusra Syeda                                      .addReg(SystemZ::R7D)
264b006f555SYusra Syeda                                      .addReg(MI->getOperand(0).getReg()));
26562ba528aSKai Nacke     emitCallInformation(CallType::BASR76);
266b006f555SYusra Syeda     return;
267b006f555SYusra Syeda 
268eb3e09c9SNeumann Hon   case SystemZ::CallBASR_STACKEXT:
269eb3e09c9SNeumann Hon     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
270eb3e09c9SNeumann Hon                                      .addReg(SystemZ::R3D)
271eb3e09c9SNeumann Hon                                      .addReg(MI->getOperand(0).getReg()));
272eb3e09c9SNeumann Hon     emitCallInformation(CallType::BASR33);
273eb3e09c9SNeumann Hon     return;
274eb3e09c9SNeumann Hon 
275f348f831SRichard Sandiford   case SystemZ::CallBRASL:
276f348f831SRichard Sandiford     LoweredMI = MCInstBuilder(SystemZ::BRASL)
277f348f831SRichard Sandiford       .addReg(SystemZ::R14D)
278f348f831SRichard Sandiford       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
279f348f831SRichard Sandiford     break;
280f348f831SRichard Sandiford 
281f348f831SRichard Sandiford   case SystemZ::CallBASR:
282f348f831SRichard Sandiford     LoweredMI = MCInstBuilder(SystemZ::BASR)
283f348f831SRichard Sandiford       .addReg(SystemZ::R14D)
284f348f831SRichard Sandiford       .addReg(MI->getOperand(0).getReg());
285f348f831SRichard Sandiford     break;
286f348f831SRichard Sandiford 
287f348f831SRichard Sandiford   case SystemZ::CallJG:
288f348f831SRichard Sandiford     LoweredMI = MCInstBuilder(SystemZ::JG)
289f348f831SRichard Sandiford       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
290f348f831SRichard Sandiford     break;
291f348f831SRichard Sandiford 
292fa2dffbcSUlrich Weigand   case SystemZ::CallBRCL:
293fa2dffbcSUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::BRCL)
294fa2dffbcSUlrich Weigand       .addImm(MI->getOperand(0).getImm())
295fa2dffbcSUlrich Weigand       .addImm(MI->getOperand(1).getImm())
296fa2dffbcSUlrich Weigand       .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT));
297fa2dffbcSUlrich Weigand     break;
298fa2dffbcSUlrich Weigand 
299f348f831SRichard Sandiford   case SystemZ::CallBR:
300ebef9216SUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::BR)
301ebef9216SUlrich Weigand       .addReg(MI->getOperand(0).getReg());
302f348f831SRichard Sandiford     break;
303f348f831SRichard Sandiford 
304848a513dSUlrich Weigand   case SystemZ::CallBCR:
305848a513dSUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::BCR)
306848a513dSUlrich Weigand       .addImm(MI->getOperand(0).getImm())
307848a513dSUlrich Weigand       .addImm(MI->getOperand(1).getImm())
308ebef9216SUlrich Weigand       .addReg(MI->getOperand(2).getReg());
309848a513dSUlrich Weigand     break;
310848a513dSUlrich Weigand 
311848a513dSUlrich Weigand   case SystemZ::CRBCall:
312848a513dSUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::CRB)
313848a513dSUlrich Weigand       .addReg(MI->getOperand(0).getReg())
314848a513dSUlrich Weigand       .addReg(MI->getOperand(1).getReg())
315848a513dSUlrich Weigand       .addImm(MI->getOperand(2).getImm())
316ebef9216SUlrich Weigand       .addReg(MI->getOperand(3).getReg())
317848a513dSUlrich Weigand       .addImm(0);
318848a513dSUlrich Weigand     break;
319848a513dSUlrich Weigand 
320848a513dSUlrich Weigand   case SystemZ::CGRBCall:
321848a513dSUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::CGRB)
322848a513dSUlrich Weigand       .addReg(MI->getOperand(0).getReg())
323848a513dSUlrich Weigand       .addReg(MI->getOperand(1).getReg())
324848a513dSUlrich Weigand       .addImm(MI->getOperand(2).getImm())
325ebef9216SUlrich Weigand       .addReg(MI->getOperand(3).getReg())
326848a513dSUlrich Weigand       .addImm(0);
327848a513dSUlrich Weigand     break;
328848a513dSUlrich Weigand 
329848a513dSUlrich Weigand   case SystemZ::CIBCall:
330848a513dSUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::CIB)
331848a513dSUlrich Weigand       .addReg(MI->getOperand(0).getReg())
332848a513dSUlrich Weigand       .addImm(MI->getOperand(1).getImm())
333848a513dSUlrich Weigand       .addImm(MI->getOperand(2).getImm())
334ebef9216SUlrich Weigand       .addReg(MI->getOperand(3).getReg())
335848a513dSUlrich Weigand       .addImm(0);
336848a513dSUlrich Weigand     break;
337848a513dSUlrich Weigand 
338848a513dSUlrich Weigand   case SystemZ::CGIBCall:
339848a513dSUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::CGIB)
340848a513dSUlrich Weigand       .addReg(MI->getOperand(0).getReg())
341848a513dSUlrich Weigand       .addImm(MI->getOperand(1).getImm())
342848a513dSUlrich Weigand       .addImm(MI->getOperand(2).getImm())
343ebef9216SUlrich Weigand       .addReg(MI->getOperand(3).getReg())
344848a513dSUlrich Weigand       .addImm(0);
345848a513dSUlrich Weigand     break;
346848a513dSUlrich Weigand 
347848a513dSUlrich Weigand   case SystemZ::CLRBCall:
348848a513dSUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::CLRB)
349848a513dSUlrich Weigand       .addReg(MI->getOperand(0).getReg())
350848a513dSUlrich Weigand       .addReg(MI->getOperand(1).getReg())
351848a513dSUlrich Weigand       .addImm(MI->getOperand(2).getImm())
352ebef9216SUlrich Weigand       .addReg(MI->getOperand(3).getReg())
353848a513dSUlrich Weigand       .addImm(0);
354848a513dSUlrich Weigand     break;
355848a513dSUlrich Weigand 
356848a513dSUlrich Weigand   case SystemZ::CLGRBCall:
357848a513dSUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
358848a513dSUlrich Weigand       .addReg(MI->getOperand(0).getReg())
359848a513dSUlrich Weigand       .addReg(MI->getOperand(1).getReg())
360848a513dSUlrich Weigand       .addImm(MI->getOperand(2).getImm())
361ebef9216SUlrich Weigand       .addReg(MI->getOperand(3).getReg())
362848a513dSUlrich Weigand       .addImm(0);
363848a513dSUlrich Weigand     break;
364848a513dSUlrich Weigand 
365848a513dSUlrich Weigand   case SystemZ::CLIBCall:
366848a513dSUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::CLIB)
367848a513dSUlrich Weigand       .addReg(MI->getOperand(0).getReg())
368848a513dSUlrich Weigand       .addImm(MI->getOperand(1).getImm())
369848a513dSUlrich Weigand       .addImm(MI->getOperand(2).getImm())
370ebef9216SUlrich Weigand       .addReg(MI->getOperand(3).getReg())
371848a513dSUlrich Weigand       .addImm(0);
372848a513dSUlrich Weigand     break;
373848a513dSUlrich Weigand 
374848a513dSUlrich Weigand   case SystemZ::CLGIBCall:
375848a513dSUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
376848a513dSUlrich Weigand       .addReg(MI->getOperand(0).getReg())
377848a513dSUlrich Weigand       .addImm(MI->getOperand(1).getImm())
378848a513dSUlrich Weigand       .addImm(MI->getOperand(2).getImm())
379ebef9216SUlrich Weigand       .addReg(MI->getOperand(3).getReg())
380848a513dSUlrich Weigand       .addImm(0);
381848a513dSUlrich Weigand     break;
382848a513dSUlrich Weigand 
3837db6918eSUlrich Weigand   case SystemZ::TLS_GDCALL:
3847db6918eSUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::BRASL)
3857db6918eSUlrich Weigand       .addReg(SystemZ::R14D)
3867db6918eSUlrich Weigand       .addExpr(getTLSGetOffset(MF->getContext()))
3877db6918eSUlrich Weigand       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD));
3887db6918eSUlrich Weigand     break;
3897db6918eSUlrich Weigand 
3907db6918eSUlrich Weigand   case SystemZ::TLS_LDCALL:
3917db6918eSUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::BRASL)
3927db6918eSUlrich Weigand       .addReg(SystemZ::R14D)
3937db6918eSUlrich Weigand       .addExpr(getTLSGetOffset(MF->getContext()))
3947db6918eSUlrich Weigand       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM));
3957db6918eSUlrich Weigand     break;
3967db6918eSUlrich Weigand 
3977db6918eSUlrich Weigand   case SystemZ::GOT:
3987db6918eSUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::LARL)
3997db6918eSUlrich Weigand       .addReg(MI->getOperand(0).getReg())
4007db6918eSUlrich Weigand       .addExpr(getGlobalOffsetTable(MF->getContext()));
4017db6918eSUlrich Weigand     break;
4027db6918eSUlrich Weigand 
403652784e2SRichard Sandiford   case SystemZ::IILF64:
404652784e2SRichard Sandiford     LoweredMI = MCInstBuilder(SystemZ::IILF)
405652784e2SRichard Sandiford       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
406652784e2SRichard Sandiford       .addImm(MI->getOperand(2).getImm());
407652784e2SRichard Sandiford     break;
408652784e2SRichard Sandiford 
40901240234SRichard Sandiford   case SystemZ::IIHF64:
41001240234SRichard Sandiford     LoweredMI = MCInstBuilder(SystemZ::IIHF)
41101240234SRichard Sandiford       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
41201240234SRichard Sandiford       .addImm(MI->getOperand(2).getImm());
41301240234SRichard Sandiford     break;
41401240234SRichard Sandiford 
4150755c93bSRichard Sandiford   case SystemZ::RISBHH:
4160755c93bSRichard Sandiford   case SystemZ::RISBHL:
4170755c93bSRichard Sandiford     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
4180755c93bSRichard Sandiford     break;
4190755c93bSRichard Sandiford 
4200755c93bSRichard Sandiford   case SystemZ::RISBLH:
4210755c93bSRichard Sandiford   case SystemZ::RISBLL:
4220755c93bSRichard Sandiford     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
4230755c93bSRichard Sandiford     break;
4240755c93bSRichard Sandiford 
425ce4c1095SUlrich Weigand   case SystemZ::VLVGP32:
426ce4c1095SUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::VLVGP)
427ce4c1095SUlrich Weigand       .addReg(MI->getOperand(0).getReg())
428ce4c1095SUlrich Weigand       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg()))
429ce4c1095SUlrich Weigand       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()));
430ce4c1095SUlrich Weigand     break;
431ce4c1095SUlrich Weigand 
43249506d78SUlrich Weigand   case SystemZ::VLR32:
43349506d78SUlrich Weigand   case SystemZ::VLR64:
43449506d78SUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::VLR)
43549506d78SUlrich Weigand       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
43649506d78SUlrich Weigand       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()));
43749506d78SUlrich Weigand     break;
43849506d78SUlrich Weigand 
4393641b10fSUlrich Weigand   case SystemZ::VL:
4403641b10fSUlrich Weigand     Lower.lower(MI, LoweredMI);
4413641b10fSUlrich Weigand     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign);
4423641b10fSUlrich Weigand     break;
4433641b10fSUlrich Weigand 
4443641b10fSUlrich Weigand   case SystemZ::VST:
4453641b10fSUlrich Weigand     Lower.lower(MI, LoweredMI);
4463641b10fSUlrich Weigand     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign);
4473641b10fSUlrich Weigand     break;
4483641b10fSUlrich Weigand 
4493641b10fSUlrich Weigand   case SystemZ::VLM:
4503641b10fSUlrich Weigand     Lower.lower(MI, LoweredMI);
4513641b10fSUlrich Weigand     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign);
4523641b10fSUlrich Weigand     break;
4533641b10fSUlrich Weigand 
4543641b10fSUlrich Weigand   case SystemZ::VSTM:
4553641b10fSUlrich Weigand     Lower.lower(MI, LoweredMI);
4563641b10fSUlrich Weigand     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign);
4573641b10fSUlrich Weigand     break;
4583641b10fSUlrich Weigand 
45949506d78SUlrich Weigand   case SystemZ::VL32:
46049506d78SUlrich Weigand     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF);
46149506d78SUlrich Weigand     break;
46249506d78SUlrich Weigand 
46349506d78SUlrich Weigand   case SystemZ::VL64:
46449506d78SUlrich Weigand     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG);
46549506d78SUlrich Weigand     break;
46649506d78SUlrich Weigand 
46749506d78SUlrich Weigand   case SystemZ::VST32:
46849506d78SUlrich Weigand     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF);
46949506d78SUlrich Weigand     break;
47049506d78SUlrich Weigand 
47149506d78SUlrich Weigand   case SystemZ::VST64:
47249506d78SUlrich Weigand     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG);
47349506d78SUlrich Weigand     break;
47449506d78SUlrich Weigand 
47580b3af7aSUlrich Weigand   case SystemZ::LFER:
47680b3af7aSUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::VLGVF)
47780b3af7aSUlrich Weigand       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg()))
47880b3af7aSUlrich Weigand       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()))
47980b3af7aSUlrich Weigand       .addReg(0).addImm(0);
48080b3af7aSUlrich Weigand     break;
48180b3af7aSUlrich Weigand 
48280b3af7aSUlrich Weigand   case SystemZ::LEFR:
48380b3af7aSUlrich Weigand     LoweredMI = MCInstBuilder(SystemZ::VLVGF)
48480b3af7aSUlrich Weigand       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
48580b3af7aSUlrich Weigand       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
48680b3af7aSUlrich Weigand       .addReg(MI->getOperand(1).getReg())
48780b3af7aSUlrich Weigand       .addReg(0).addImm(0);
48880b3af7aSUlrich Weigand     break;
48980b3af7aSUlrich Weigand 
490652784e2SRichard Sandiford #define LOWER_LOW(NAME)                                                 \
491652784e2SRichard Sandiford   case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
492652784e2SRichard Sandiford 
493652784e2SRichard Sandiford   LOWER_LOW(IILL);
494652784e2SRichard Sandiford   LOWER_LOW(IILH);
495f03789caSRichard Sandiford   LOWER_LOW(TMLL);
496f03789caSRichard Sandiford   LOWER_LOW(TMLH);
497652784e2SRichard Sandiford   LOWER_LOW(NILL);
498652784e2SRichard Sandiford   LOWER_LOW(NILH);
499652784e2SRichard Sandiford   LOWER_LOW(NILF);
500652784e2SRichard Sandiford   LOWER_LOW(OILL);
501652784e2SRichard Sandiford   LOWER_LOW(OILH);
502652784e2SRichard Sandiford   LOWER_LOW(OILF);
503652784e2SRichard Sandiford   LOWER_LOW(XILF);
504652784e2SRichard Sandiford 
505652784e2SRichard Sandiford #undef LOWER_LOW
506652784e2SRichard Sandiford 
5071a56931bSRichard Sandiford #define LOWER_HIGH(NAME) \
5081a56931bSRichard Sandiford   case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
5091a56931bSRichard Sandiford 
5101a56931bSRichard Sandiford   LOWER_HIGH(IIHL);
5111a56931bSRichard Sandiford   LOWER_HIGH(IIHH);
512f03789caSRichard Sandiford   LOWER_HIGH(TMHL);
513f03789caSRichard Sandiford   LOWER_HIGH(TMHH);
5147028428cSRichard Sandiford   LOWER_HIGH(NIHL);
5157028428cSRichard Sandiford   LOWER_HIGH(NIHH);
5167028428cSRichard Sandiford   LOWER_HIGH(NIHF);
5176e96ac60SRichard Sandiford   LOWER_HIGH(OIHL);
5186e96ac60SRichard Sandiford   LOWER_HIGH(OIHH);
5196e96ac60SRichard Sandiford   LOWER_HIGH(OIHF);
5205718dacbSRichard Sandiford   LOWER_HIGH(XIHF);
5211a56931bSRichard Sandiford 
5221a56931bSRichard Sandiford #undef LOWER_HIGH
5231a56931bSRichard Sandiford 
5249afe613dSRichard Sandiford   case SystemZ::Serialize:
525d84f5d30SEric Christopher     if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())
526d2148cafSUlrich Weigand       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
5279afe613dSRichard Sandiford         .addImm(14).addReg(SystemZ::R0D);
5289afe613dSRichard Sandiford     else
529d2148cafSUlrich Weigand       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
5309afe613dSRichard Sandiford         .addImm(15).addReg(SystemZ::R0D);
5319afe613dSRichard Sandiford     break;
5329afe613dSRichard Sandiford 
533a9ac6d6cSUlrich Weigand   // Emit nothing here but a comment if we can.
534a9ac6d6cSUlrich Weigand   case SystemZ::MemBarrier:
535a9ac6d6cSUlrich Weigand     OutStreamer->emitRawComment("MEMBARRIER");
536a9ac6d6cSUlrich Weigand     return;
537a9ac6d6cSUlrich Weigand 
538ab42cbceSZhan Jun Liau   // We want to emit "j .+2" for traps, jumping to the relative immediate field
539ab42cbceSZhan Jun Liau   // of the jump instruction, which is an illegal instruction. We cannot emit a
540ab42cbceSZhan Jun Liau   // "." symbol, so create and emit a temp label before the instruction and use
541ab42cbceSZhan Jun Liau   // that instead.
542ab42cbceSZhan Jun Liau   case SystemZ::Trap: {
543ab42cbceSZhan Jun Liau     MCSymbol *DotSym = OutContext.createTempSymbol();
5446d2d589bSFangrui Song     OutStreamer->emitLabel(DotSym);
545ab42cbceSZhan Jun Liau 
546ab42cbceSZhan Jun Liau     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
547ab42cbceSZhan Jun Liau     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
548ab42cbceSZhan Jun Liau     LoweredMI = MCInstBuilder(SystemZ::J)
549ab42cbceSZhan Jun Liau       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
550ab42cbceSZhan Jun Liau     }
551ab42cbceSZhan Jun Liau     break;
552ab42cbceSZhan Jun Liau 
553ab42cbceSZhan Jun Liau   // Conditional traps will create a branch on condition instruction that jumps
554ab42cbceSZhan Jun Liau   // to the relative immediate field of the jump instruction. (eg. "jo .+2")
555ab42cbceSZhan Jun Liau   case SystemZ::CondTrap: {
556ab42cbceSZhan Jun Liau     MCSymbol *DotSym = OutContext.createTempSymbol();
5576d2d589bSFangrui Song     OutStreamer->emitLabel(DotSym);
558ab42cbceSZhan Jun Liau 
559ab42cbceSZhan Jun Liau     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
560ab42cbceSZhan Jun Liau     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
561ab42cbceSZhan Jun Liau     LoweredMI = MCInstBuilder(SystemZ::BRC)
562ab42cbceSZhan Jun Liau       .addImm(MI->getOperand(0).getImm())
563ab42cbceSZhan Jun Liau       .addImm(MI->getOperand(1).getImm())
564ab42cbceSZhan Jun Liau       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
565ab42cbceSZhan Jun Liau     }
566ab42cbceSZhan Jun Liau     break;
567ab42cbceSZhan Jun Liau 
568f1241581SJonas Paulsson   case TargetOpcode::FENTRY_CALL:
569f1241581SJonas Paulsson     LowerFENTRY_CALL(*MI, Lower);
570f1241581SJonas Paulsson     return;
571f1241581SJonas Paulsson 
5725eb64110SUlrich Weigand   case TargetOpcode::STACKMAP:
5735eb64110SUlrich Weigand     LowerSTACKMAP(*MI);
5745eb64110SUlrich Weigand     return;
5755eb64110SUlrich Weigand 
5765eb64110SUlrich Weigand   case TargetOpcode::PATCHPOINT:
5775eb64110SUlrich Weigand     LowerPATCHPOINT(*MI, Lower);
5785eb64110SUlrich Weigand     return;
5795eb64110SUlrich Weigand 
58037a92f3bSJonas Paulsson   case SystemZ::EXRL_Pseudo: {
58137a92f3bSJonas Paulsson     unsigned TargetInsOpc = MI->getOperand(0).getImm();
58237a92f3bSJonas Paulsson     Register LenMinus1Reg = MI->getOperand(1).getReg();
58337a92f3bSJonas Paulsson     Register DestReg = MI->getOperand(2).getReg();
58437a92f3bSJonas Paulsson     int64_t DestDisp = MI->getOperand(3).getImm();
58537a92f3bSJonas Paulsson     Register SrcReg = MI->getOperand(4).getReg();
58637a92f3bSJonas Paulsson     int64_t SrcDisp = MI->getOperand(5).getImm();
58737a92f3bSJonas Paulsson 
588a48b43f9SJonas Paulsson     SystemZTargetStreamer *TS = getTargetStreamer();
58937a92f3bSJonas Paulsson     MCSymbol *DotSym = nullptr;
59037a92f3bSJonas Paulsson     MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg)
59137a92f3bSJonas Paulsson       .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp);
592a48b43f9SJonas Paulsson     SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
593a48b43f9SJonas Paulsson     SystemZTargetStreamer::EXRLT2SymMap::iterator I =
594a48b43f9SJonas Paulsson         TS->EXRLTargets2Sym.find(ET_STI);
595a48b43f9SJonas Paulsson     if (I != TS->EXRLTargets2Sym.end())
59637a92f3bSJonas Paulsson       DotSym = I->second;
59737a92f3bSJonas Paulsson     else
598a48b43f9SJonas Paulsson       TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol();
59937a92f3bSJonas Paulsson     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
60037a92f3bSJonas Paulsson     EmitToStreamer(
60137a92f3bSJonas Paulsson         *OutStreamer,
60237a92f3bSJonas Paulsson         MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot));
60337a92f3bSJonas Paulsson     return;
60437a92f3bSJonas Paulsson   }
60537a92f3bSJonas Paulsson 
6069ab97cd1SRichard Sandiford   default:
607f348f831SRichard Sandiford     Lower.lower(MI, LoweredMI);
6089ab97cd1SRichard Sandiford     break;
6099ab97cd1SRichard Sandiford   }
6109ff69c8fSLang Hames   EmitToStreamer(*OutStreamer, LoweredMI);
6115f613dfdSUlrich Weigand }
6125f613dfdSUlrich Weigand 
6135eb64110SUlrich Weigand // Emit the largest nop instruction smaller than or equal to NumBytes
6145eb64110SUlrich Weigand // bytes.  Return the size of nop emitted.
EmitNop(MCContext & OutContext,MCStreamer & OutStreamer,unsigned NumBytes,const MCSubtargetInfo & STI)6155eb64110SUlrich Weigand static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
6165eb64110SUlrich Weigand                         unsigned NumBytes, const MCSubtargetInfo &STI) {
6175eb64110SUlrich Weigand   if (NumBytes < 2) {
6185eb64110SUlrich Weigand     llvm_unreachable("Zero nops?");
6195eb64110SUlrich Weigand     return 0;
6205eb64110SUlrich Weigand   }
6215eb64110SUlrich Weigand   else if (NumBytes < 4) {
622bcd24b2dSFangrui Song     OutStreamer.emitInstruction(
623bcd24b2dSFangrui Song         MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
6245eb64110SUlrich Weigand     return 2;
6255eb64110SUlrich Weigand   }
6265eb64110SUlrich Weigand   else if (NumBytes < 6) {
627bcd24b2dSFangrui Song     OutStreamer.emitInstruction(
628bcd24b2dSFangrui Song         MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
6295eb64110SUlrich Weigand         STI);
6305eb64110SUlrich Weigand     return 4;
6315eb64110SUlrich Weigand   }
6325eb64110SUlrich Weigand   else {
6335eb64110SUlrich Weigand     MCSymbol *DotSym = OutContext.createTempSymbol();
6345eb64110SUlrich Weigand     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
6356d2d589bSFangrui Song     OutStreamer.emitLabel(DotSym);
636bcd24b2dSFangrui Song     OutStreamer.emitInstruction(
637bcd24b2dSFangrui Song         MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
6385eb64110SUlrich Weigand     return 6;
6395eb64110SUlrich Weigand   }
6405eb64110SUlrich Weigand }
6415eb64110SUlrich Weigand 
LowerFENTRY_CALL(const MachineInstr & MI,SystemZMCInstLower & Lower)642f1241581SJonas Paulsson void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
643f1241581SJonas Paulsson                                          SystemZMCInstLower &Lower) {
644f1241581SJonas Paulsson   MCContext &Ctx = MF->getContext();
6456be15788SJonas Paulsson   if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
6466be15788SJonas Paulsson     MCSymbol *DotSym = OutContext.createTempSymbol();
64715d82c62SFangrui Song     OutStreamer->pushSection();
648adf4142fSFangrui Song     OutStreamer->switchSection(
6496be15788SJonas Paulsson         Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
6506d2d589bSFangrui Song     OutStreamer->emitSymbolValue(DotSym, 8);
65115d82c62SFangrui Song     OutStreamer->popSection();
6526d2d589bSFangrui Song     OutStreamer->emitLabel(DotSym);
6536be15788SJonas Paulsson   }
6546be15788SJonas Paulsson 
655ca520592SJonas Paulsson   if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
6566e504d77SJonas Paulsson     EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());
6576e504d77SJonas Paulsson     return;
6586e504d77SJonas Paulsson   }
6596e504d77SJonas Paulsson 
660f1241581SJonas Paulsson   MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
661f1241581SJonas Paulsson   const MCSymbolRefExpr *Op =
662f1241581SJonas Paulsson       MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx);
663bcd24b2dSFangrui Song   OutStreamer->emitInstruction(
664bcd24b2dSFangrui Song       MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
665bcd24b2dSFangrui Song       getSubtargetInfo());
666f1241581SJonas Paulsson }
667f1241581SJonas Paulsson 
LowerSTACKMAP(const MachineInstr & MI)6685eb64110SUlrich Weigand void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
6693432d40cSJonas Paulsson   auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo();
6705eb64110SUlrich Weigand 
6715eb64110SUlrich Weigand   unsigned NumNOPBytes = MI.getOperand(1).getImm();
6725eb64110SUlrich Weigand 
6738277c91cSPhilip Reames   auto &Ctx = OutStreamer->getContext();
6748277c91cSPhilip Reames   MCSymbol *MILabel = Ctx.createTempSymbol();
6756d2d589bSFangrui Song   OutStreamer->emitLabel(MILabel);
6768277c91cSPhilip Reames 
6778277c91cSPhilip Reames   SM.recordStackMap(*MILabel, MI);
6785eb64110SUlrich Weigand   assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");
6795eb64110SUlrich Weigand 
6805eb64110SUlrich Weigand   // Scan ahead to trim the shadow.
6815eb64110SUlrich Weigand   unsigned ShadowBytes = 0;
6825eb64110SUlrich Weigand   const MachineBasicBlock &MBB = *MI.getParent();
6835eb64110SUlrich Weigand   MachineBasicBlock::const_iterator MII(MI);
6845eb64110SUlrich Weigand   ++MII;
6855eb64110SUlrich Weigand   while (ShadowBytes < NumNOPBytes) {
6865eb64110SUlrich Weigand     if (MII == MBB.end() ||
6875eb64110SUlrich Weigand         MII->getOpcode() == TargetOpcode::PATCHPOINT ||
6885eb64110SUlrich Weigand         MII->getOpcode() == TargetOpcode::STACKMAP)
6895eb64110SUlrich Weigand       break;
6905eb64110SUlrich Weigand     ShadowBytes += TII->getInstSizeInBytes(*MII);
6915eb64110SUlrich Weigand     if (MII->isCall())
6925eb64110SUlrich Weigand       break;
6935eb64110SUlrich Weigand     ++MII;
6945eb64110SUlrich Weigand   }
6955eb64110SUlrich Weigand 
6965eb64110SUlrich Weigand   // Emit nops.
6975eb64110SUlrich Weigand   while (ShadowBytes < NumNOPBytes)
6985eb64110SUlrich Weigand     ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
6995eb64110SUlrich Weigand                            getSubtargetInfo());
7005eb64110SUlrich Weigand }
7015eb64110SUlrich Weigand 
7025eb64110SUlrich Weigand // Lower a patchpoint of the form:
7035eb64110SUlrich Weigand // [<def>], <id>, <numBytes>, <target>, <numArgs>
LowerPATCHPOINT(const MachineInstr & MI,SystemZMCInstLower & Lower)7045eb64110SUlrich Weigand void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
7055eb64110SUlrich Weigand                                         SystemZMCInstLower &Lower) {
7068277c91cSPhilip Reames   auto &Ctx = OutStreamer->getContext();
7078277c91cSPhilip Reames   MCSymbol *MILabel = Ctx.createTempSymbol();
7086d2d589bSFangrui Song   OutStreamer->emitLabel(MILabel);
7098277c91cSPhilip Reames 
7108277c91cSPhilip Reames   SM.recordPatchPoint(*MILabel, MI);
7115eb64110SUlrich Weigand   PatchPointOpers Opers(&MI);
7125eb64110SUlrich Weigand 
7135eb64110SUlrich Weigand   unsigned EncodedBytes = 0;
7145eb64110SUlrich Weigand   const MachineOperand &CalleeMO = Opers.getCallTarget();
7155eb64110SUlrich Weigand 
7165eb64110SUlrich Weigand   if (CalleeMO.isImm()) {
7175eb64110SUlrich Weigand     uint64_t CallTarget = CalleeMO.getImm();
7185eb64110SUlrich Weigand     if (CallTarget) {
7195eb64110SUlrich Weigand       unsigned ScratchIdx = -1;
7205eb64110SUlrich Weigand       unsigned ScratchReg = 0;
7215eb64110SUlrich Weigand       do {
7225eb64110SUlrich Weigand         ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);
7235eb64110SUlrich Weigand         ScratchReg = MI.getOperand(ScratchIdx).getReg();
7245eb64110SUlrich Weigand       } while (ScratchReg == SystemZ::R0D);
7255eb64110SUlrich Weigand 
7265eb64110SUlrich Weigand       // Materialize the call target address
7275eb64110SUlrich Weigand       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
7285eb64110SUlrich Weigand                                       .addReg(ScratchReg)
7295eb64110SUlrich Weigand                                       .addImm(CallTarget & 0xFFFFFFFF));
7305eb64110SUlrich Weigand       EncodedBytes += 6;
7315eb64110SUlrich Weigand       if (CallTarget >> 32) {
7325eb64110SUlrich Weigand         EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
7335eb64110SUlrich Weigand                                         .addReg(ScratchReg)
7345eb64110SUlrich Weigand                                         .addImm(CallTarget >> 32));
7355eb64110SUlrich Weigand         EncodedBytes += 6;
7365eb64110SUlrich Weigand       }
7375eb64110SUlrich Weigand 
7385eb64110SUlrich Weigand       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
7395eb64110SUlrich Weigand                                      .addReg(SystemZ::R14D)
7405eb64110SUlrich Weigand                                      .addReg(ScratchReg));
7415eb64110SUlrich Weigand       EncodedBytes += 2;
7425eb64110SUlrich Weigand     }
7435eb64110SUlrich Weigand   } else if (CalleeMO.isGlobal()) {
7445eb64110SUlrich Weigand     const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT);
7455eb64110SUlrich Weigand     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
7465eb64110SUlrich Weigand                                    .addReg(SystemZ::R14D)
7475eb64110SUlrich Weigand                                    .addExpr(Expr));
7485eb64110SUlrich Weigand     EncodedBytes += 6;
7495eb64110SUlrich Weigand   }
7505eb64110SUlrich Weigand 
7515eb64110SUlrich Weigand   // Emit padding.
7525eb64110SUlrich Weigand   unsigned NumBytes = Opers.getNumPatchBytes();
7535eb64110SUlrich Weigand   assert(NumBytes >= EncodedBytes &&
7545eb64110SUlrich Weigand          "Patchpoint can't request size less than the length of a call.");
7555eb64110SUlrich Weigand   assert((NumBytes - EncodedBytes) % 2 == 0 &&
7565eb64110SUlrich Weigand          "Invalid number of NOP bytes requested!");
7575eb64110SUlrich Weigand   while (EncodedBytes < NumBytes)
7585eb64110SUlrich Weigand     EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,
7595eb64110SUlrich Weigand                             getSubtargetInfo());
7605eb64110SUlrich Weigand }
7615eb64110SUlrich Weigand 
7625f613dfdSUlrich Weigand // Convert a SystemZ-specific constant pool modifier into the associated
7635f613dfdSUlrich Weigand // MCSymbolRefExpr variant kind.
7645f613dfdSUlrich Weigand static MCSymbolRefExpr::VariantKind
getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier)7655f613dfdSUlrich Weigand getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
7665f613dfdSUlrich Weigand   switch (Modifier) {
7677db6918eSUlrich Weigand   case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
7687db6918eSUlrich Weigand   case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM;
7697db6918eSUlrich Weigand   case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF;
7705f613dfdSUlrich Weigand   case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
7715f613dfdSUlrich Weigand   }
7725f613dfdSUlrich Weigand   llvm_unreachable("Invalid SystemCPModifier!");
7735f613dfdSUlrich Weigand }
7745f613dfdSUlrich Weigand 
emitMachineConstantPoolValue(MachineConstantPoolValue * MCPV)7751d49eb00SFangrui Song void SystemZAsmPrinter::emitMachineConstantPoolValue(
7761d49eb00SFangrui Song     MachineConstantPoolValue *MCPV) {
77721f5d68aSRichard Sandiford   auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
7785f613dfdSUlrich Weigand 
7795f613dfdSUlrich Weigand   const MCExpr *Expr =
78013760bd1SJim Grosbach     MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()),
7815f613dfdSUlrich Weigand                             getModifierVariantKind(ZCPV->getModifier()),
7825f613dfdSUlrich Weigand                             OutContext);
783bd7287ebSMehdi Amini   uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
7845f613dfdSUlrich Weigand 
78577497103SFangrui Song   OutStreamer->emitValue(Expr, Size);
7865f613dfdSUlrich Weigand }
7875f613dfdSUlrich Weigand 
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & OS)7885277b3ffSNick Desaulniers bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
7895f613dfdSUlrich Weigand                                         const char *ExtraCode,
7905f613dfdSUlrich Weigand                                         raw_ostream &OS) {
791458eac25SJonas Paulsson   const MCRegisterInfo &MRI = *TM.getMCRegisterInfo();
79296421af5SJonas Paulsson   const MachineOperand &MO = MI->getOperand(OpNo);
79396421af5SJonas Paulsson   MCOperand MCOp;
794458eac25SJonas Paulsson   if (ExtraCode) {
795458eac25SJonas Paulsson     if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() &&
796458eac25SJonas Paulsson         SystemZ::GR128BitRegClass.contains(MO.getReg()))
79796421af5SJonas Paulsson       MCOp =
79896421af5SJonas Paulsson           MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64));
799458eac25SJonas Paulsson     else
8007ab164c4SNick Desaulniers       return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
80196421af5SJonas Paulsson   } else {
80269c1d631SRafael Espindola     SystemZMCInstLower Lower(MF->getContext(), *this);
80396421af5SJonas Paulsson     MCOp = Lower.lowerOperand(MO);
80496421af5SJonas Paulsson   }
805458eac25SJonas Paulsson   SystemZInstPrinter::printOperand(MCOp, MAI, OS);
8065f613dfdSUlrich Weigand   return false;
8075f613dfdSUlrich Weigand }
8085f613dfdSUlrich Weigand 
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & OS)8095f613dfdSUlrich Weigand bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
8105f613dfdSUlrich Weigand                                               unsigned OpNo,
8115f613dfdSUlrich Weigand                                               const char *ExtraCode,
8125f613dfdSUlrich Weigand                                               raw_ostream &OS) {
8131c3ef9efSJonas Paulsson   SystemZInstPrinter::
8141c3ef9efSJonas Paulsson     printAddress(MAI, MI->getOperand(OpNo).getReg(),
8151c3ef9efSJonas Paulsson                  MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()),
8165f613dfdSUlrich Weigand                  MI->getOperand(OpNo + 2).getReg(), OS);
8175f613dfdSUlrich Weigand   return false;
8185f613dfdSUlrich Weigand }
8195f613dfdSUlrich Weigand 
emitEndOfAsmFile(Module & M)8200dce409cSFangrui Song void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
82130c804bbSThan McIntosh   emitStackMaps(SM);
8225eb64110SUlrich Weigand }
8235eb64110SUlrich Weigand 
emitFunctionBodyEnd()8245ac411aeSYusra Syeda void SystemZAsmPrinter::emitFunctionBodyEnd() {
8255ac411aeSYusra Syeda   if (TM.getTargetTriple().isOSzOS()) {
8265ac411aeSYusra Syeda     // Emit symbol for the end of function if the z/OS target streamer
8275ac411aeSYusra Syeda     // is used. This is needed to calculate the size of the function.
8285ac411aeSYusra Syeda     MCSymbol *FnEndSym = createTempSymbol("func_end");
8295ac411aeSYusra Syeda     OutStreamer->emitLabel(FnEndSym);
8305ac411aeSYusra Syeda 
83115d82c62SFangrui Song     OutStreamer->pushSection();
832adf4142fSFangrui Song     OutStreamer->switchSection(getObjFileLowering().getPPA1Section());
8335ac411aeSYusra Syeda     emitPPA1(FnEndSym);
83415d82c62SFangrui Song     OutStreamer->popSection();
8355ac411aeSYusra Syeda 
8365ac411aeSYusra Syeda     CurrentFnPPA1Sym = nullptr;
8375ac411aeSYusra Syeda     CurrentFnEPMarkerSym = nullptr;
8385ac411aeSYusra Syeda   }
8395ac411aeSYusra Syeda }
8405ac411aeSYusra Syeda 
emitPPA1Flags(std::unique_ptr<MCStreamer> & OutStreamer,bool VarArg,bool StackProtector,bool FPRMask,bool VRMask)8415ac411aeSYusra Syeda static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
8425ac411aeSYusra Syeda                           bool StackProtector, bool FPRMask, bool VRMask) {
8435ac411aeSYusra Syeda   enum class PPA1Flag1 : uint8_t {
8445ac411aeSYusra Syeda     DSA64Bit = (0x80 >> 0),
8455ac411aeSYusra Syeda     VarArg = (0x80 >> 7),
8465ac411aeSYusra Syeda     LLVM_MARK_AS_BITMASK_ENUM(DSA64Bit)
8475ac411aeSYusra Syeda   };
8485ac411aeSYusra Syeda   enum class PPA1Flag2 : uint8_t {
8495ac411aeSYusra Syeda     ExternalProcedure = (0x80 >> 0),
8505ac411aeSYusra Syeda     STACKPROTECTOR = (0x80 >> 3),
8515ac411aeSYusra Syeda     LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure)
8525ac411aeSYusra Syeda   };
8535ac411aeSYusra Syeda   enum class PPA1Flag3 : uint8_t {
8545ac411aeSYusra Syeda     FPRMask = (0x80 >> 2),
8555ac411aeSYusra Syeda     LLVM_MARK_AS_BITMASK_ENUM(FPRMask)
8565ac411aeSYusra Syeda   };
8575ac411aeSYusra Syeda   enum class PPA1Flag4 : uint8_t {
8585ac411aeSYusra Syeda     EPMOffsetPresent = (0x80 >> 0),
8595ac411aeSYusra Syeda     VRMask = (0x80 >> 2),
8605ac411aeSYusra Syeda     ProcedureNamePresent = (0x80 >> 7),
8615ac411aeSYusra Syeda     LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent)
8625ac411aeSYusra Syeda   };
8635ac411aeSYusra Syeda 
8645ac411aeSYusra Syeda   // Declare optional section flags that can be modified.
8655ac411aeSYusra Syeda   auto Flags1 = PPA1Flag1(0);
8665ac411aeSYusra Syeda   auto Flags2 = PPA1Flag2::ExternalProcedure;
8675ac411aeSYusra Syeda   auto Flags3 = PPA1Flag3(0);
8685ac411aeSYusra Syeda   auto Flags4 = PPA1Flag4::EPMOffsetPresent | PPA1Flag4::ProcedureNamePresent;
8695ac411aeSYusra Syeda 
8705ac411aeSYusra Syeda   Flags1 |= PPA1Flag1::DSA64Bit;
8715ac411aeSYusra Syeda 
8725ac411aeSYusra Syeda   if (VarArg)
8735ac411aeSYusra Syeda     Flags1 |= PPA1Flag1::VarArg;
8745ac411aeSYusra Syeda 
8755ac411aeSYusra Syeda   if (StackProtector)
8765ac411aeSYusra Syeda     Flags2 |= PPA1Flag2::STACKPROTECTOR;
8775ac411aeSYusra Syeda 
8785ac411aeSYusra Syeda   // SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in.
8795ac411aeSYusra Syeda   if (FPRMask)
8805ac411aeSYusra Syeda     Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag.
8815ac411aeSYusra Syeda 
8825ac411aeSYusra Syeda   if (VRMask)
8835ac411aeSYusra Syeda     Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag.
8845ac411aeSYusra Syeda 
8855ac411aeSYusra Syeda   OutStreamer->AddComment("PPA1 Flags 1");
8865ac411aeSYusra Syeda   if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit)
8875ac411aeSYusra Syeda     OutStreamer->AddComment("  Bit 0: 1 = 64-bit DSA");
8885ac411aeSYusra Syeda   else
8895ac411aeSYusra Syeda     OutStreamer->AddComment("  Bit 0: 0 = 32-bit DSA");
8905ac411aeSYusra Syeda   if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg)
8915ac411aeSYusra Syeda     OutStreamer->AddComment("  Bit 7: 1 = Vararg function");
8925ac411aeSYusra Syeda   OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1.
8935ac411aeSYusra Syeda 
8945ac411aeSYusra Syeda   OutStreamer->AddComment("PPA1 Flags 2");
8955ac411aeSYusra Syeda   if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure)
8965ac411aeSYusra Syeda     OutStreamer->AddComment("  Bit 0: 1 = External procedure");
8975ac411aeSYusra Syeda   if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR)
8985ac411aeSYusra Syeda     OutStreamer->AddComment("  Bit 3: 1 = STACKPROTECT is enabled");
8995ac411aeSYusra Syeda   else
9005ac411aeSYusra Syeda     OutStreamer->AddComment("  Bit 3: 0 = STACKPROTECT is not enabled");
9015ac411aeSYusra Syeda   OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2.
9025ac411aeSYusra Syeda 
9035ac411aeSYusra Syeda   OutStreamer->AddComment("PPA1 Flags 3");
9045ac411aeSYusra Syeda   if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask)
9055ac411aeSYusra Syeda     OutStreamer->AddComment("  Bit 2: 1 = FP Reg Mask is in optional area");
9065ac411aeSYusra Syeda   OutStreamer->emitInt8(
9075ac411aeSYusra Syeda       static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections).
9085ac411aeSYusra Syeda 
9095ac411aeSYusra Syeda   OutStreamer->AddComment("PPA1 Flags 4");
9105ac411aeSYusra Syeda   if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask)
9115ac411aeSYusra Syeda     OutStreamer->AddComment("  Bit 2: 1 = Vector Reg Mask is in optional area");
9125ac411aeSYusra Syeda   OutStreamer->emitInt8(static_cast<uint8_t>(
9135ac411aeSYusra Syeda       Flags4)); // Flags 4 (optional sections, always emit these).
9145ac411aeSYusra Syeda }
9155ac411aeSYusra Syeda 
emitPPA1(MCSymbol * FnEndSym)9165ac411aeSYusra Syeda void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
9175ac411aeSYusra Syeda   const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
9185ac411aeSYusra Syeda   const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
9195ac411aeSYusra Syeda   const auto TargetHasVector = Subtarget.hasVector();
9205ac411aeSYusra Syeda 
9215ac411aeSYusra Syeda   const SystemZMachineFunctionInfo *ZFI =
9225ac411aeSYusra Syeda       MF->getInfo<SystemZMachineFunctionInfo>();
9235ac411aeSYusra Syeda   const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>(
9245ac411aeSYusra Syeda       Subtarget.getFrameLowering());
9255ac411aeSYusra Syeda   const MachineFrameInfo &MFFrame = MF->getFrameInfo();
9265ac411aeSYusra Syeda 
9275ac411aeSYusra Syeda   // Get saved GPR/FPR/VPR masks.
9285ac411aeSYusra Syeda   const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();
9295ac411aeSYusra Syeda   uint16_t SavedGPRMask = 0;
9305ac411aeSYusra Syeda   uint16_t SavedFPRMask = 0;
9315ac411aeSYusra Syeda   uint8_t SavedVRMask = 0;
9325ac411aeSYusra Syeda   int64_t OffsetFPR = 0;
9335ac411aeSYusra Syeda   int64_t OffsetVR = 0;
9345ac411aeSYusra Syeda   const int64_t TopOfStack =
9355ac411aeSYusra Syeda       MFFrame.getOffsetAdjustment() + MFFrame.getStackSize();
9365ac411aeSYusra Syeda 
9375ac411aeSYusra Syeda   // Loop over the spilled registers. The CalleeSavedInfo can't be used because
9385ac411aeSYusra Syeda   // it does not contain all spilled registers.
9395ac411aeSYusra Syeda   for (unsigned I = ZFI->getSpillGPRRegs().LowGPR,
9405ac411aeSYusra Syeda                 E = ZFI->getSpillGPRRegs().HighGPR;
9415ac411aeSYusra Syeda        I && E && I <= E; ++I) {
9425ac411aeSYusra Syeda     unsigned V = TRI->getEncodingValue((Register)I);
9435ac411aeSYusra Syeda     assert(V < 16 && "GPR index out of range");
9445ac411aeSYusra Syeda     SavedGPRMask |= 1 << (15 - V);
9455ac411aeSYusra Syeda   }
9465ac411aeSYusra Syeda 
9475ac411aeSYusra Syeda   for (auto &CS : CSI) {
9485ac411aeSYusra Syeda     unsigned Reg = CS.getReg();
9495ac411aeSYusra Syeda     unsigned I = TRI->getEncodingValue(Reg);
9505ac411aeSYusra Syeda 
9515ac411aeSYusra Syeda     if (SystemZ::FP64BitRegClass.contains(Reg)) {
9525ac411aeSYusra Syeda       assert(I < 16 && "FPR index out of range");
9535ac411aeSYusra Syeda       SavedFPRMask |= 1 << (15 - I);
9545ac411aeSYusra Syeda       int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
9555ac411aeSYusra Syeda       if (Temp < OffsetFPR)
9565ac411aeSYusra Syeda         OffsetFPR = Temp;
9575ac411aeSYusra Syeda     } else if (SystemZ::VR128BitRegClass.contains(Reg)) {
9585ac411aeSYusra Syeda       assert(I >= 16 && I <= 23 && "VPR index out of range");
9595ac411aeSYusra Syeda       unsigned BitNum = I - 16;
9605ac411aeSYusra Syeda       SavedVRMask |= 1 << (7 - BitNum);
9615ac411aeSYusra Syeda       int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
9625ac411aeSYusra Syeda       if (Temp < OffsetVR)
9635ac411aeSYusra Syeda         OffsetVR = Temp;
9645ac411aeSYusra Syeda     }
9655ac411aeSYusra Syeda   }
9665ac411aeSYusra Syeda 
9675ac411aeSYusra Syeda   // Adjust the offset.
9685ac411aeSYusra Syeda   OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0;
9695ac411aeSYusra Syeda   OffsetVR += (OffsetVR < 0) ? TopOfStack : 0;
9705ac411aeSYusra Syeda 
9715ac411aeSYusra Syeda   // Get alloca register.
9725ac411aeSYusra Syeda   uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF));
9735ac411aeSYusra Syeda   uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0;
9745ac411aeSYusra Syeda   assert(AllocaReg < 16 && "Can't have alloca register larger than 15");
9758801a5d1SNAKAMURA Takumi   (void)AllocaReg;
9765ac411aeSYusra Syeda 
9775ac411aeSYusra Syeda   // Build FPR save area offset.
9785ac411aeSYusra Syeda   uint32_t FrameAndFPROffset = 0;
9795ac411aeSYusra Syeda   if (SavedFPRMask) {
9805ac411aeSYusra Syeda     uint64_t FPRSaveAreaOffset = OffsetFPR;
9815ac411aeSYusra Syeda     assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range");
9825ac411aeSYusra Syeda 
9835ac411aeSYusra Syeda     FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
9845ac411aeSYusra Syeda     FrameAndFPROffset |= FrameReg << 28;                // Put into top 4 bits.
9855ac411aeSYusra Syeda   }
9865ac411aeSYusra Syeda 
9875ac411aeSYusra Syeda   // Build VR save area offset.
9885ac411aeSYusra Syeda   uint32_t FrameAndVROffset = 0;
9895ac411aeSYusra Syeda   if (TargetHasVector && SavedVRMask) {
9905ac411aeSYusra Syeda     uint64_t VRSaveAreaOffset = OffsetVR;
9915ac411aeSYusra Syeda     assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range");
9925ac411aeSYusra Syeda 
9935ac411aeSYusra Syeda     FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
9945ac411aeSYusra Syeda     FrameAndVROffset |= FrameReg << 28;               // Put into top 4 bits.
9955ac411aeSYusra Syeda   }
9965ac411aeSYusra Syeda 
9975ac411aeSYusra Syeda   // Emit PPA1 section.
9985ac411aeSYusra Syeda   OutStreamer->AddComment("PPA1");
9995ac411aeSYusra Syeda   OutStreamer->emitLabel(CurrentFnPPA1Sym);
10005ac411aeSYusra Syeda   OutStreamer->AddComment("Version");
10015ac411aeSYusra Syeda   OutStreamer->emitInt8(0x02); // Version.
10025ac411aeSYusra Syeda   OutStreamer->AddComment("LE Signature X'CE'");
10035ac411aeSYusra Syeda   OutStreamer->emitInt8(0xCE); // CEL signature.
10045ac411aeSYusra Syeda   OutStreamer->AddComment("Saved GPR Mask");
10055ac411aeSYusra Syeda   OutStreamer->emitInt16(SavedGPRMask);
10065ac411aeSYusra Syeda 
10075ac411aeSYusra Syeda   emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(),
10085ac411aeSYusra Syeda                 MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0,
10095ac411aeSYusra Syeda                 TargetHasVector && SavedVRMask != 0);
10105ac411aeSYusra Syeda 
10115ac411aeSYusra Syeda   OutStreamer->AddComment("Length/4 of Parms");
10125ac411aeSYusra Syeda   OutStreamer->emitInt16(
10135ac411aeSYusra Syeda       static_cast<uint16_t>(MFFrame.getMaxCallFrameSize() / 4)); // Parms/4.
10145ac411aeSYusra Syeda   OutStreamer->AddComment("Length of Code");
10155ac411aeSYusra Syeda   OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4);
10165ac411aeSYusra Syeda 
10175ac411aeSYusra Syeda   // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3).
10185ac411aeSYusra Syeda   if (SavedFPRMask) {
10195ac411aeSYusra Syeda     OutStreamer->AddComment("FPR mask");
10205ac411aeSYusra Syeda     OutStreamer->emitInt16(SavedFPRMask);
10215ac411aeSYusra Syeda     OutStreamer->AddComment("AR mask");
10225ac411aeSYusra Syeda     OutStreamer->emitInt16(0); // AR Mask, unused currently.
10235ac411aeSYusra Syeda     OutStreamer->AddComment("FPR Save Area Locator");
10245ac411aeSYusra Syeda     OutStreamer->AddComment(Twine("  Bit 0-3: Register R")
10255ac411aeSYusra Syeda                                 .concat(utostr(FrameAndFPROffset >> 28))
10265ac411aeSYusra Syeda                                 .str());
10275ac411aeSYusra Syeda     OutStreamer->AddComment(Twine("  Bit 4-31: Offset ")
10285ac411aeSYusra Syeda                                 .concat(utostr(FrameAndFPROffset & 0x0FFFFFFF))
10295ac411aeSYusra Syeda                                 .str());
10305ac411aeSYusra Syeda     OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with
10315ac411aeSYusra Syeda                                                // register to add value to
10325ac411aeSYusra Syeda                                                // (alloca reg).
10335ac411aeSYusra Syeda   }
10345ac411aeSYusra Syeda 
10355ac411aeSYusra Syeda   // Emit saved VR mask to VR save area.
10365ac411aeSYusra Syeda   if (TargetHasVector && SavedVRMask) {
10375ac411aeSYusra Syeda     OutStreamer->AddComment("VR mask");
10385ac411aeSYusra Syeda     OutStreamer->emitInt8(SavedVRMask);
10395ac411aeSYusra Syeda     OutStreamer->emitInt8(0);  // Reserved.
10405ac411aeSYusra Syeda     OutStreamer->emitInt16(0); // Also reserved.
10415ac411aeSYusra Syeda     OutStreamer->AddComment("VR Save Area Locator");
10425ac411aeSYusra Syeda     OutStreamer->AddComment(Twine("  Bit 0-3: Register R")
10435ac411aeSYusra Syeda                                 .concat(utostr(FrameAndVROffset >> 28))
10445ac411aeSYusra Syeda                                 .str());
10455ac411aeSYusra Syeda     OutStreamer->AddComment(Twine("  Bit 4-31: Offset ")
10465ac411aeSYusra Syeda                                 .concat(utostr(FrameAndVROffset & 0x0FFFFFFF))
10475ac411aeSYusra Syeda                                 .str());
10485ac411aeSYusra Syeda     OutStreamer->emitInt32(FrameAndVROffset);
10495ac411aeSYusra Syeda   }
10505ac411aeSYusra Syeda 
10515ac411aeSYusra Syeda   // Emit offset to entry point optional section (0x80 of flags 4).
10525ac411aeSYusra Syeda   OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym,
10535ac411aeSYusra Syeda                                       4);
10545ac411aeSYusra Syeda }
10555ac411aeSYusra Syeda 
emitFunctionEntryLabel()1056fc8a0876SYusra Syeda void SystemZAsmPrinter::emitFunctionEntryLabel() {
1057ad73ce31SZongwei Lan   const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
1058fc8a0876SYusra Syeda 
1059fc8a0876SYusra Syeda   if (Subtarget.getTargetTriple().isOSzOS()) {
1060fc8a0876SYusra Syeda     MCContext &OutContext = OutStreamer->getContext();
10615ac411aeSYusra Syeda 
10625ac411aeSYusra Syeda     // Save information for later use.
10635ac411aeSYusra Syeda     std::string N(MF->getFunction().hasName()
10645ac411aeSYusra Syeda                       ? Twine(MF->getFunction().getName()).concat("_").str()
10655ac411aeSYusra Syeda                       : "");
10665ac411aeSYusra Syeda 
10675ac411aeSYusra Syeda     CurrentFnEPMarkerSym =
10685ac411aeSYusra Syeda         OutContext.createTempSymbol(Twine("EPM_").concat(N).str(), true);
10695ac411aeSYusra Syeda     CurrentFnPPA1Sym =
10705ac411aeSYusra Syeda         OutContext.createTempSymbol(Twine("PPA1_").concat(N).str(), true);
1071fc8a0876SYusra Syeda 
1072fc8a0876SYusra Syeda     // EntryPoint Marker
1073fc8a0876SYusra Syeda     const MachineFrameInfo &MFFrame = MF->getFrameInfo();
1074fc8a0876SYusra Syeda     bool IsUsingAlloca = MFFrame.hasVarSizedObjects();
1075fc8a0876SYusra Syeda 
1076fc8a0876SYusra Syeda     // Set Flags
1077fc8a0876SYusra Syeda     uint8_t Flags = 0;
1078fc8a0876SYusra Syeda     if (IsUsingAlloca)
1079fc8a0876SYusra Syeda       Flags |= 0x04;
1080fc8a0876SYusra Syeda 
1081fc8a0876SYusra Syeda     uint32_t DSASize = MFFrame.getStackSize();
1082fc8a0876SYusra Syeda 
1083fc8a0876SYusra Syeda     // Combine into top 27 bits of DSASize and bottom 5 bits of Flags.
1084fc8a0876SYusra Syeda     uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5
1085fc8a0876SYusra Syeda     DSAAndFlags |= Flags;
1086fc8a0876SYusra Syeda 
1087fc8a0876SYusra Syeda     // Emit entry point marker section.
1088fc8a0876SYusra Syeda     OutStreamer->AddComment("XPLINK Routine Layout Entry");
10895ac411aeSYusra Syeda     OutStreamer->emitLabel(CurrentFnEPMarkerSym);
1090fc8a0876SYusra Syeda     OutStreamer->AddComment("Eyecatcher 0x00C300C500C500");
1091fc8a0876SYusra Syeda     OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher.
1092fc8a0876SYusra Syeda     OutStreamer->AddComment("Mark Type C'1'");
1093fc8a0876SYusra Syeda     OutStreamer->emitInt8(0xF1); // Mark Type.
10945ac411aeSYusra Syeda     OutStreamer->AddComment("Offset to PPA1");
10955ac411aeSYusra Syeda     OutStreamer->emitAbsoluteSymbolDiff(CurrentFnPPA1Sym, CurrentFnEPMarkerSym,
10965ac411aeSYusra Syeda                                         4);
1097fc8a0876SYusra Syeda     if (OutStreamer->isVerboseAsm()) {
1098fc8a0876SYusra Syeda       OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
1099fc8a0876SYusra Syeda       OutStreamer->AddComment("Entry Flags");
1100fc8a0876SYusra Syeda       if (Flags & 0x04)
1101fc8a0876SYusra Syeda         OutStreamer->AddComment("  Bit 2: 1 = Uses alloca");
1102fc8a0876SYusra Syeda       else
1103fc8a0876SYusra Syeda         OutStreamer->AddComment("  Bit 2: 0 = Does not use alloca");
1104fc8a0876SYusra Syeda     }
1105fc8a0876SYusra Syeda     OutStreamer->emitInt32(DSAAndFlags);
1106fc8a0876SYusra Syeda   }
1107fc8a0876SYusra Syeda 
1108fc8a0876SYusra Syeda   AsmPrinter::emitFunctionEntryLabel();
1109fc8a0876SYusra Syeda }
1110fc8a0876SYusra Syeda 
11115f613dfdSUlrich Weigand // Force static initialization.
LLVMInitializeSystemZAsmPrinter()11120dbcb363STom Stellard extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() {
1113f42454b9SMehdi Amini   RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget());
11145f613dfdSUlrich Weigand }
1115