xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinter.cpp (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
1 //===- SystemZInstPrinter.cpp - Convert SystemZ MCInst to assembly syntax -===//
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 "SystemZInstPrinter.h"
10 #include "llvm/MC/MCExpr.h"
11 #include "llvm/MC/MCInst.h"
12 #include "llvm/MC/MCRegister.h"
13 #include "llvm/MC/MCSymbol.h"
14 #include "llvm/Support/Casting.h"
15 #include "llvm/Support/ErrorHandling.h"
16 #include "llvm/Support/MathExtras.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include <cassert>
19 #include <cstdint>
20 
21 using namespace llvm;
22 
23 #define DEBUG_TYPE "asm-printer"
24 
25 #include "SystemZGenAsmWriter.inc"
26 
27 void SystemZInstPrinter::printAddress(const MCAsmInfo *MAI, MCRegister Base,
28                                       const MCOperand &DispMO, MCRegister Index,
29                                       raw_ostream &O) {
30   printOperand(DispMO, MAI, O);
31   if (Base || Index) {
32     O << '(';
33     if (Index) {
34       printFormattedRegName(MAI, Index, O);
35       if (Base)
36         O << ',';
37     }
38     if (Base)
39       printFormattedRegName(MAI, Base, O);
40     O << ')';
41   }
42 }
43 
44 void SystemZInstPrinter::printOperand(const MCOperand &MO, const MCAsmInfo *MAI,
45                                       raw_ostream &O) {
46   if (MO.isReg()) {
47     if (!MO.getReg())
48       O << '0';
49     else
50       printFormattedRegName(MAI, MO.getReg(), O);
51   }
52   else if (MO.isImm())
53     O << markup("<imm:") << MO.getImm() << markup(">");
54   else if (MO.isExpr())
55     MO.getExpr()->print(O, MAI);
56   else
57     llvm_unreachable("Invalid operand");
58 }
59 
60 void SystemZInstPrinter::printFormattedRegName(const MCAsmInfo *MAI,
61                                                MCRegister Reg,
62                                                raw_ostream &O) const {
63   const char *RegName = getRegisterName(Reg);
64   if (MAI->getAssemblerDialect() == AD_HLASM) {
65     // Skip register prefix so that only register number is left
66     assert(isalpha(RegName[0]) && isdigit(RegName[1]));
67     O << markup("<reg:") << (RegName + 1) << markup(">");
68   } else
69     O << markup("<reg:") << '%' << RegName << markup(">");
70 }
71 
72 void SystemZInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) const {
73   printFormattedRegName(&MAI, Reg, O);
74 }
75 
76 void SystemZInstPrinter::printInst(const MCInst *MI, uint64_t Address,
77                                    StringRef Annot, const MCSubtargetInfo &STI,
78                                    raw_ostream &O) {
79   printInstruction(MI, Address, O);
80   printAnnotation(O, Annot);
81 }
82 
83 template <unsigned N>
84 void SystemZInstPrinter::printUImmOperand(const MCInst *MI, int OpNum,
85                                           raw_ostream &O) {
86   const MCOperand &MO = MI->getOperand(OpNum);
87   if (MO.isExpr()) {
88     O << *MO.getExpr();
89     return;
90   }
91   uint64_t Value = static_cast<uint64_t>(MO.getImm());
92   assert(isUInt<N>(Value) && "Invalid uimm argument");
93   O << markup("<imm:") << Value << markup(">");
94 }
95 
96 template <unsigned N>
97 void SystemZInstPrinter::printSImmOperand(const MCInst *MI, int OpNum,
98                                           raw_ostream &O) {
99   const MCOperand &MO = MI->getOperand(OpNum);
100   if (MO.isExpr()) {
101     O << *MO.getExpr();
102     return;
103   }
104   int64_t Value = MI->getOperand(OpNum).getImm();
105   assert(isInt<N>(Value) && "Invalid simm argument");
106   O << markup("<imm:") << Value << markup(">");
107 }
108 
109 void SystemZInstPrinter::printU1ImmOperand(const MCInst *MI, int OpNum,
110                                            raw_ostream &O) {
111   printUImmOperand<1>(MI, OpNum, O);
112 }
113 
114 void SystemZInstPrinter::printU2ImmOperand(const MCInst *MI, int OpNum,
115                                            raw_ostream &O) {
116   printUImmOperand<2>(MI, OpNum, O);
117 }
118 
119 void SystemZInstPrinter::printU3ImmOperand(const MCInst *MI, int OpNum,
120                                            raw_ostream &O) {
121   printUImmOperand<3>(MI, OpNum, O);
122 }
123 
124 void SystemZInstPrinter::printU4ImmOperand(const MCInst *MI, int OpNum,
125                                            raw_ostream &O) {
126   printUImmOperand<4>(MI, OpNum, O);
127 }
128 
129 void SystemZInstPrinter::printS8ImmOperand(const MCInst *MI, int OpNum,
130                                            raw_ostream &O) {
131   printSImmOperand<8>(MI, OpNum, O);
132 }
133 
134 void SystemZInstPrinter::printU8ImmOperand(const MCInst *MI, int OpNum,
135                                            raw_ostream &O) {
136   printUImmOperand<8>(MI, OpNum, O);
137 }
138 
139 void SystemZInstPrinter::printU12ImmOperand(const MCInst *MI, int OpNum,
140                                             raw_ostream &O) {
141   printUImmOperand<12>(MI, OpNum, O);
142 }
143 
144 void SystemZInstPrinter::printS16ImmOperand(const MCInst *MI, int OpNum,
145                                             raw_ostream &O) {
146   printSImmOperand<16>(MI, OpNum, O);
147 }
148 
149 void SystemZInstPrinter::printU16ImmOperand(const MCInst *MI, int OpNum,
150                                             raw_ostream &O) {
151   printUImmOperand<16>(MI, OpNum, O);
152 }
153 
154 void SystemZInstPrinter::printS32ImmOperand(const MCInst *MI, int OpNum,
155                                             raw_ostream &O) {
156   printSImmOperand<32>(MI, OpNum, O);
157 }
158 
159 void SystemZInstPrinter::printU32ImmOperand(const MCInst *MI, int OpNum,
160                                             raw_ostream &O) {
161   printUImmOperand<32>(MI, OpNum, O);
162 }
163 
164 void SystemZInstPrinter::printU48ImmOperand(const MCInst *MI, int OpNum,
165                                             raw_ostream &O) {
166   printUImmOperand<48>(MI, OpNum, O);
167 }
168 
169 void SystemZInstPrinter::printPCRelOperand(const MCInst *MI, int OpNum,
170                                            raw_ostream &O) {
171   const MCOperand &MO = MI->getOperand(OpNum);
172   if (MO.isImm()) {
173     O << markup("<imm:") << "0x";
174     O.write_hex(MO.getImm());
175     O << markup(">");
176   } else
177     MO.getExpr()->print(O, &MAI);
178 }
179 
180 void SystemZInstPrinter::printPCRelTLSOperand(const MCInst *MI,
181                                               uint64_t Address, int OpNum,
182                                               raw_ostream &O) {
183   // Output the PC-relative operand.
184   printPCRelOperand(MI, OpNum, O);
185 
186   // Output the TLS marker if present.
187   if ((unsigned)OpNum + 1 < MI->getNumOperands()) {
188     const MCOperand &MO = MI->getOperand(OpNum + 1);
189     const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*MO.getExpr());
190     switch (refExp.getKind()) {
191       case MCSymbolRefExpr::VK_TLSGD:
192         O << ":tls_gdcall:";
193         break;
194       case MCSymbolRefExpr::VK_TLSLDM:
195         O << ":tls_ldcall:";
196         break;
197       default:
198         llvm_unreachable("Unexpected symbol kind");
199     }
200     O << refExp.getSymbol().getName();
201   }
202 }
203 
204 void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum,
205                                       raw_ostream &O) {
206   printOperand(MI->getOperand(OpNum), &MAI, O);
207 }
208 
209 void SystemZInstPrinter::printBDAddrOperand(const MCInst *MI, int OpNum,
210                                             raw_ostream &O) {
211   printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
212                0, O);
213 }
214 
215 void SystemZInstPrinter::printBDXAddrOperand(const MCInst *MI, int OpNum,
216                                              raw_ostream &O) {
217   printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
218                MI->getOperand(OpNum + 2).getReg(), O);
219 }
220 
221 void SystemZInstPrinter::printBDLAddrOperand(const MCInst *MI, int OpNum,
222                                              raw_ostream &O) {
223   unsigned Base = MI->getOperand(OpNum).getReg();
224   const MCOperand &DispMO = MI->getOperand(OpNum + 1);
225   uint64_t Length = MI->getOperand(OpNum + 2).getImm();
226   printOperand(DispMO, &MAI, O);
227   O << '(' << Length;
228   if (Base) {
229     O << ",";
230     printRegName(O, Base);
231   }
232   O << ')';
233 }
234 
235 void SystemZInstPrinter::printBDRAddrOperand(const MCInst *MI, int OpNum,
236                                              raw_ostream &O) {
237   unsigned Base = MI->getOperand(OpNum).getReg();
238   const MCOperand &DispMO = MI->getOperand(OpNum + 1);
239   unsigned Length = MI->getOperand(OpNum + 2).getReg();
240   printOperand(DispMO, &MAI, O);
241   O << "(";
242   printRegName(O, Length);
243   if (Base) {
244     O << ",";
245     printRegName(O, Base);
246   }
247   O << ')';
248 }
249 
250 void SystemZInstPrinter::printBDVAddrOperand(const MCInst *MI, int OpNum,
251                                              raw_ostream &O) {
252   printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
253                MI->getOperand(OpNum + 2).getReg(), O);
254 }
255 
256 void SystemZInstPrinter::printCond4Operand(const MCInst *MI, int OpNum,
257                                            raw_ostream &O) {
258   static const char *const CondNames[] = {
259     "o", "h", "nle", "l", "nhe", "lh", "ne",
260     "e", "nlh", "he", "nl", "le", "nh", "no"
261   };
262   uint64_t Imm = MI->getOperand(OpNum).getImm();
263   assert(Imm > 0 && Imm < 15 && "Invalid condition");
264   O << CondNames[Imm - 1];
265 }
266