xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinterCommon.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //=- SystemZInstPrinterCommon.cpp - Common SystemZ MCInst to assembly funcs -=//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric 
9*700637cbSDimitry Andric #include "SystemZInstPrinterCommon.h"
10*700637cbSDimitry Andric #include "MCTargetDesc/SystemZMCAsmInfo.h"
11*700637cbSDimitry Andric #include "llvm/MC/MCExpr.h"
12*700637cbSDimitry Andric #include "llvm/MC/MCInst.h"
13*700637cbSDimitry Andric #include "llvm/MC/MCRegister.h"
14*700637cbSDimitry Andric #include "llvm/MC/MCSymbol.h"
15*700637cbSDimitry Andric #include "llvm/Support/Casting.h"
16*700637cbSDimitry Andric #include "llvm/Support/ErrorHandling.h"
17*700637cbSDimitry Andric #include "llvm/Support/MathExtras.h"
18*700637cbSDimitry Andric #include "llvm/Support/raw_ostream.h"
19*700637cbSDimitry Andric #include <cassert>
20*700637cbSDimitry Andric #include <cstdint>
21*700637cbSDimitry Andric 
22*700637cbSDimitry Andric using namespace llvm;
23*700637cbSDimitry Andric 
24*700637cbSDimitry Andric #define DEBUG_TYPE "asm-printer"
25*700637cbSDimitry Andric 
printAddress(const MCAsmInfo * MAI,MCRegister Base,const MCOperand & DispMO,MCRegister Index,raw_ostream & O)26*700637cbSDimitry Andric void SystemZInstPrinterCommon::printAddress(const MCAsmInfo *MAI,
27*700637cbSDimitry Andric                                             MCRegister Base,
28*700637cbSDimitry Andric                                             const MCOperand &DispMO,
29*700637cbSDimitry Andric                                             MCRegister Index, raw_ostream &O) {
30*700637cbSDimitry Andric   printOperand(DispMO, MAI, O);
31*700637cbSDimitry Andric   if (Base || Index) {
32*700637cbSDimitry Andric     O << '(';
33*700637cbSDimitry Andric     if (Index) {
34*700637cbSDimitry Andric       printRegName(O, Index);
35*700637cbSDimitry Andric       O << ',';
36*700637cbSDimitry Andric     }
37*700637cbSDimitry Andric     if (Base)
38*700637cbSDimitry Andric       printRegName(O, Base);
39*700637cbSDimitry Andric     else
40*700637cbSDimitry Andric       O << '0';
41*700637cbSDimitry Andric     O << ')';
42*700637cbSDimitry Andric   }
43*700637cbSDimitry Andric }
44*700637cbSDimitry Andric 
printOperand(const MCOperand & MO,const MCAsmInfo * MAI,raw_ostream & O)45*700637cbSDimitry Andric void SystemZInstPrinterCommon::printOperand(const MCOperand &MO,
46*700637cbSDimitry Andric                                             const MCAsmInfo *MAI,
47*700637cbSDimitry Andric                                             raw_ostream &O) {
48*700637cbSDimitry Andric   if (MO.isReg()) {
49*700637cbSDimitry Andric     if (!MO.getReg())
50*700637cbSDimitry Andric       O << '0';
51*700637cbSDimitry Andric     else
52*700637cbSDimitry Andric       printRegName(O, MO.getReg());
53*700637cbSDimitry Andric   } else if (MO.isImm())
54*700637cbSDimitry Andric     markup(O, Markup::Immediate) << MO.getImm();
55*700637cbSDimitry Andric   else if (MO.isExpr())
56*700637cbSDimitry Andric     MAI->printExpr(O, *MO.getExpr());
57*700637cbSDimitry Andric   else
58*700637cbSDimitry Andric     llvm_unreachable("Invalid operand");
59*700637cbSDimitry Andric }
60*700637cbSDimitry Andric 
printRegName(raw_ostream & O,MCRegister Reg)61*700637cbSDimitry Andric void SystemZInstPrinterCommon::printRegName(raw_ostream &O, MCRegister Reg) {
62*700637cbSDimitry Andric   printFormattedRegName(&MAI, Reg, O);
63*700637cbSDimitry Andric }
64*700637cbSDimitry Andric 
65*700637cbSDimitry Andric template <unsigned N>
printUImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)66*700637cbSDimitry Andric void SystemZInstPrinterCommon::printUImmOperand(const MCInst *MI, int OpNum,
67*700637cbSDimitry Andric                                                 raw_ostream &O) {
68*700637cbSDimitry Andric   const MCOperand &MO = MI->getOperand(OpNum);
69*700637cbSDimitry Andric   if (MO.isExpr()) {
70*700637cbSDimitry Andric     MAI.printExpr(O, *MO.getExpr());
71*700637cbSDimitry Andric     return;
72*700637cbSDimitry Andric   }
73*700637cbSDimitry Andric   uint64_t Value = static_cast<uint64_t>(MO.getImm());
74*700637cbSDimitry Andric   assert(isUInt<N>(Value) && "Invalid uimm argument");
75*700637cbSDimitry Andric   markup(O, Markup::Immediate) << Value;
76*700637cbSDimitry Andric }
77*700637cbSDimitry Andric 
78*700637cbSDimitry Andric template <unsigned N>
printSImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)79*700637cbSDimitry Andric void SystemZInstPrinterCommon::printSImmOperand(const MCInst *MI, int OpNum,
80*700637cbSDimitry Andric                                                 raw_ostream &O) {
81*700637cbSDimitry Andric   const MCOperand &MO = MI->getOperand(OpNum);
82*700637cbSDimitry Andric   if (MO.isExpr()) {
83*700637cbSDimitry Andric     MAI.printExpr(O, *MO.getExpr());
84*700637cbSDimitry Andric     return;
85*700637cbSDimitry Andric   }
86*700637cbSDimitry Andric   int64_t Value = MI->getOperand(OpNum).getImm();
87*700637cbSDimitry Andric   assert(isInt<N>(Value) && "Invalid simm argument");
88*700637cbSDimitry Andric   markup(O, Markup::Immediate) << Value;
89*700637cbSDimitry Andric }
90*700637cbSDimitry Andric 
printU1ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)91*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU1ImmOperand(const MCInst *MI, int OpNum,
92*700637cbSDimitry Andric                                                  raw_ostream &O) {
93*700637cbSDimitry Andric   printUImmOperand<1>(MI, OpNum, O);
94*700637cbSDimitry Andric }
95*700637cbSDimitry Andric 
printU2ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)96*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU2ImmOperand(const MCInst *MI, int OpNum,
97*700637cbSDimitry Andric                                                  raw_ostream &O) {
98*700637cbSDimitry Andric   printUImmOperand<2>(MI, OpNum, O);
99*700637cbSDimitry Andric }
100*700637cbSDimitry Andric 
printU3ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)101*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU3ImmOperand(const MCInst *MI, int OpNum,
102*700637cbSDimitry Andric                                                  raw_ostream &O) {
103*700637cbSDimitry Andric   printUImmOperand<3>(MI, OpNum, O);
104*700637cbSDimitry Andric }
105*700637cbSDimitry Andric 
printU4ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)106*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU4ImmOperand(const MCInst *MI, int OpNum,
107*700637cbSDimitry Andric                                                  raw_ostream &O) {
108*700637cbSDimitry Andric   printUImmOperand<4>(MI, OpNum, O);
109*700637cbSDimitry Andric }
110*700637cbSDimitry Andric 
printS8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)111*700637cbSDimitry Andric void SystemZInstPrinterCommon::printS8ImmOperand(const MCInst *MI, int OpNum,
112*700637cbSDimitry Andric                                                  raw_ostream &O) {
113*700637cbSDimitry Andric   printSImmOperand<8>(MI, OpNum, O);
114*700637cbSDimitry Andric }
115*700637cbSDimitry Andric 
printU8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)116*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU8ImmOperand(const MCInst *MI, int OpNum,
117*700637cbSDimitry Andric                                                  raw_ostream &O) {
118*700637cbSDimitry Andric   printUImmOperand<8>(MI, OpNum, O);
119*700637cbSDimitry Andric }
120*700637cbSDimitry Andric 
printU12ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)121*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU12ImmOperand(const MCInst *MI, int OpNum,
122*700637cbSDimitry Andric                                                   raw_ostream &O) {
123*700637cbSDimitry Andric   printUImmOperand<12>(MI, OpNum, O);
124*700637cbSDimitry Andric }
125*700637cbSDimitry Andric 
printS16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)126*700637cbSDimitry Andric void SystemZInstPrinterCommon::printS16ImmOperand(const MCInst *MI, int OpNum,
127*700637cbSDimitry Andric                                                   raw_ostream &O) {
128*700637cbSDimitry Andric   printSImmOperand<16>(MI, OpNum, O);
129*700637cbSDimitry Andric }
130*700637cbSDimitry Andric 
printU16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)131*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU16ImmOperand(const MCInst *MI, int OpNum,
132*700637cbSDimitry Andric                                                   raw_ostream &O) {
133*700637cbSDimitry Andric   printUImmOperand<16>(MI, OpNum, O);
134*700637cbSDimitry Andric }
135*700637cbSDimitry Andric 
printS32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)136*700637cbSDimitry Andric void SystemZInstPrinterCommon::printS32ImmOperand(const MCInst *MI, int OpNum,
137*700637cbSDimitry Andric                                                   raw_ostream &O) {
138*700637cbSDimitry Andric   printSImmOperand<32>(MI, OpNum, O);
139*700637cbSDimitry Andric }
140*700637cbSDimitry Andric 
printU32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)141*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU32ImmOperand(const MCInst *MI, int OpNum,
142*700637cbSDimitry Andric                                                   raw_ostream &O) {
143*700637cbSDimitry Andric   printUImmOperand<32>(MI, OpNum, O);
144*700637cbSDimitry Andric }
145*700637cbSDimitry Andric 
printU48ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)146*700637cbSDimitry Andric void SystemZInstPrinterCommon::printU48ImmOperand(const MCInst *MI, int OpNum,
147*700637cbSDimitry Andric                                                   raw_ostream &O) {
148*700637cbSDimitry Andric   printUImmOperand<48>(MI, OpNum, O);
149*700637cbSDimitry Andric }
150*700637cbSDimitry Andric 
printPCRelOperand(const MCInst * MI,uint64_t Address,int OpNum,raw_ostream & O)151*700637cbSDimitry Andric void SystemZInstPrinterCommon::printPCRelOperand(const MCInst *MI,
152*700637cbSDimitry Andric                                                  uint64_t Address, int OpNum,
153*700637cbSDimitry Andric                                                  raw_ostream &O) {
154*700637cbSDimitry Andric   const MCOperand &MO = MI->getOperand(OpNum);
155*700637cbSDimitry Andric 
156*700637cbSDimitry Andric   // If the label has already been resolved to an immediate offset (say, when
157*700637cbSDimitry Andric   // we're running the disassembler), just print the immediate.
158*700637cbSDimitry Andric   if (MO.isImm()) {
159*700637cbSDimitry Andric     int64_t Offset = MO.getImm();
160*700637cbSDimitry Andric     if (PrintBranchImmAsAddress)
161*700637cbSDimitry Andric       markup(O, Markup::Target) << formatHex(Address + Offset);
162*700637cbSDimitry Andric     else
163*700637cbSDimitry Andric       markup(O, Markup::Immediate) << formatImm(Offset);
164*700637cbSDimitry Andric     return;
165*700637cbSDimitry Andric   }
166*700637cbSDimitry Andric 
167*700637cbSDimitry Andric   // If the branch target is simply an address then print it in hex.
168*700637cbSDimitry Andric   const MCConstantExpr *BranchTarget = dyn_cast<MCConstantExpr>(MO.getExpr());
169*700637cbSDimitry Andric   int64_t TargetAddress;
170*700637cbSDimitry Andric   if (BranchTarget && BranchTarget->evaluateAsAbsolute(TargetAddress)) {
171*700637cbSDimitry Andric     markup(O, Markup::Target) << formatHex((uint64_t)TargetAddress);
172*700637cbSDimitry Andric   } else {
173*700637cbSDimitry Andric     // Otherwise, just print the expression.
174*700637cbSDimitry Andric     MAI.printExpr(O, *MO.getExpr());
175*700637cbSDimitry Andric   }
176*700637cbSDimitry Andric }
177*700637cbSDimitry Andric 
printPCRelTLSOperand(const MCInst * MI,uint64_t Address,int OpNum,raw_ostream & O)178*700637cbSDimitry Andric void SystemZInstPrinterCommon::printPCRelTLSOperand(const MCInst *MI,
179*700637cbSDimitry Andric                                                     uint64_t Address, int OpNum,
180*700637cbSDimitry Andric                                                     raw_ostream &O) {
181*700637cbSDimitry Andric   // Output the PC-relative operand.
182*700637cbSDimitry Andric   printPCRelOperand(MI, Address, OpNum, O);
183*700637cbSDimitry Andric 
184*700637cbSDimitry Andric   // Output the TLS marker if present.
185*700637cbSDimitry Andric   if ((unsigned)OpNum + 1 < MI->getNumOperands()) {
186*700637cbSDimitry Andric     const MCOperand &MO = MI->getOperand(OpNum + 1);
187*700637cbSDimitry Andric     const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*MO.getExpr());
188*700637cbSDimitry Andric     switch (refExp.getSpecifier()) {
189*700637cbSDimitry Andric     case SystemZ::S_TLSGD:
190*700637cbSDimitry Andric       O << ":tls_gdcall:";
191*700637cbSDimitry Andric       break;
192*700637cbSDimitry Andric     case SystemZ::S_TLSLDM:
193*700637cbSDimitry Andric       O << ":tls_ldcall:";
194*700637cbSDimitry Andric       break;
195*700637cbSDimitry Andric     default:
196*700637cbSDimitry Andric       llvm_unreachable("Unexpected symbol kind");
197*700637cbSDimitry Andric     }
198*700637cbSDimitry Andric     O << refExp.getSymbol().getName();
199*700637cbSDimitry Andric   }
200*700637cbSDimitry Andric }
201*700637cbSDimitry Andric 
printOperand(const MCInst * MI,int OpNum,raw_ostream & O)202*700637cbSDimitry Andric void SystemZInstPrinterCommon::printOperand(const MCInst *MI, int OpNum,
203*700637cbSDimitry Andric                                             raw_ostream &O) {
204*700637cbSDimitry Andric   printOperand(MI->getOperand(OpNum), &MAI, O);
205*700637cbSDimitry Andric }
206*700637cbSDimitry Andric 
printBDAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)207*700637cbSDimitry Andric void SystemZInstPrinterCommon::printBDAddrOperand(const MCInst *MI, int OpNum,
208*700637cbSDimitry Andric                                                   raw_ostream &O) {
209*700637cbSDimitry Andric   printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
210*700637cbSDimitry Andric                0, O);
211*700637cbSDimitry Andric }
212*700637cbSDimitry Andric 
printBDXAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)213*700637cbSDimitry Andric void SystemZInstPrinterCommon::printBDXAddrOperand(const MCInst *MI, int OpNum,
214*700637cbSDimitry Andric                                                    raw_ostream &O) {
215*700637cbSDimitry Andric   printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
216*700637cbSDimitry Andric                MI->getOperand(OpNum + 2).getReg(), O);
217*700637cbSDimitry Andric }
218*700637cbSDimitry Andric 
printBDLAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)219*700637cbSDimitry Andric void SystemZInstPrinterCommon::printBDLAddrOperand(const MCInst *MI, int OpNum,
220*700637cbSDimitry Andric                                                    raw_ostream &O) {
221*700637cbSDimitry Andric   unsigned Base = MI->getOperand(OpNum).getReg();
222*700637cbSDimitry Andric   const MCOperand &DispMO = MI->getOperand(OpNum + 1);
223*700637cbSDimitry Andric   uint64_t Length = MI->getOperand(OpNum + 2).getImm();
224*700637cbSDimitry Andric   printOperand(DispMO, &MAI, O);
225*700637cbSDimitry Andric   O << '(' << Length;
226*700637cbSDimitry Andric   if (Base) {
227*700637cbSDimitry Andric     O << ",";
228*700637cbSDimitry Andric     printRegName(O, Base);
229*700637cbSDimitry Andric   }
230*700637cbSDimitry Andric   O << ')';
231*700637cbSDimitry Andric }
232*700637cbSDimitry Andric 
printBDRAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)233*700637cbSDimitry Andric void SystemZInstPrinterCommon::printBDRAddrOperand(const MCInst *MI, int OpNum,
234*700637cbSDimitry Andric                                                    raw_ostream &O) {
235*700637cbSDimitry Andric   unsigned Base = MI->getOperand(OpNum).getReg();
236*700637cbSDimitry Andric   const MCOperand &DispMO = MI->getOperand(OpNum + 1);
237*700637cbSDimitry Andric   unsigned Length = MI->getOperand(OpNum + 2).getReg();
238*700637cbSDimitry Andric   printOperand(DispMO, &MAI, O);
239*700637cbSDimitry Andric   O << "(";
240*700637cbSDimitry Andric   printRegName(O, Length);
241*700637cbSDimitry Andric   if (Base) {
242*700637cbSDimitry Andric     O << ",";
243*700637cbSDimitry Andric     printRegName(O, Base);
244*700637cbSDimitry Andric   }
245*700637cbSDimitry Andric   O << ')';
246*700637cbSDimitry Andric }
247*700637cbSDimitry Andric 
printBDVAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)248*700637cbSDimitry Andric void SystemZInstPrinterCommon::printBDVAddrOperand(const MCInst *MI, int OpNum,
249*700637cbSDimitry Andric                                                    raw_ostream &O) {
250*700637cbSDimitry Andric   printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
251*700637cbSDimitry Andric                MI->getOperand(OpNum + 2).getReg(), O);
252*700637cbSDimitry Andric }
253*700637cbSDimitry Andric 
printLXAAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)254*700637cbSDimitry Andric void SystemZInstPrinterCommon::printLXAAddrOperand(const MCInst *MI, int OpNum,
255*700637cbSDimitry Andric                                              raw_ostream &O) {
256*700637cbSDimitry Andric   printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
257*700637cbSDimitry Andric                MI->getOperand(OpNum + 2).getReg(), O);
258*700637cbSDimitry Andric }
259*700637cbSDimitry Andric 
printCond4Operand(const MCInst * MI,int OpNum,raw_ostream & O)260*700637cbSDimitry Andric void SystemZInstPrinterCommon::printCond4Operand(const MCInst *MI, int OpNum,
261*700637cbSDimitry Andric                                                  raw_ostream &O) {
262*700637cbSDimitry Andric   static const char *const CondNames[] = {"o",  "h",  "nle", "l",   "nhe",
263*700637cbSDimitry Andric                                           "lh", "ne", "e",   "nlh", "he",
264*700637cbSDimitry Andric                                           "nl", "le", "nh",  "no"};
265*700637cbSDimitry Andric   uint64_t Imm = MI->getOperand(OpNum).getImm();
266*700637cbSDimitry Andric   assert(Imm > 0 && Imm < 15 && "Invalid condition");
267*700637cbSDimitry Andric   O << CondNames[Imm - 1];
268*700637cbSDimitry Andric }
269