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