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   int64_t Value = MI->getOperand(OpNum).getImm();
87   assert(isUInt<N>(Value) && "Invalid uimm argument");
88   O << markup("<imm:") << Value << markup(">");
89 }
90 
91 template <unsigned N>
92 void SystemZInstPrinter::printSImmOperand(const MCInst *MI, int OpNum,
93                                           raw_ostream &O) {
94   int64_t Value = MI->getOperand(OpNum).getImm();
95   assert(isInt<N>(Value) && "Invalid simm argument");
96   O << markup("<imm:") << Value << markup(">");
97 }
98 
99 void SystemZInstPrinter::printU1ImmOperand(const MCInst *MI, int OpNum,
100                                            raw_ostream &O) {
101   printUImmOperand<1>(MI, OpNum, O);
102 }
103 
104 void SystemZInstPrinter::printU2ImmOperand(const MCInst *MI, int OpNum,
105                                            raw_ostream &O) {
106   printUImmOperand<2>(MI, OpNum, O);
107 }
108 
109 void SystemZInstPrinter::printU3ImmOperand(const MCInst *MI, int OpNum,
110                                            raw_ostream &O) {
111   printUImmOperand<3>(MI, OpNum, O);
112 }
113 
114 void SystemZInstPrinter::printU4ImmOperand(const MCInst *MI, int OpNum,
115                                            raw_ostream &O) {
116   printUImmOperand<4>(MI, OpNum, O);
117 }
118 
119 void SystemZInstPrinter::printU6ImmOperand(const MCInst *MI, int OpNum,
120                                            raw_ostream &O) {
121   printUImmOperand<6>(MI, OpNum, O);
122 }
123 
124 void SystemZInstPrinter::printS8ImmOperand(const MCInst *MI, int OpNum,
125                                            raw_ostream &O) {
126   printSImmOperand<8>(MI, OpNum, O);
127 }
128 
129 void SystemZInstPrinter::printU8ImmOperand(const MCInst *MI, int OpNum,
130                                            raw_ostream &O) {
131   printUImmOperand<8>(MI, OpNum, O);
132 }
133 
134 void SystemZInstPrinter::printU12ImmOperand(const MCInst *MI, int OpNum,
135                                             raw_ostream &O) {
136   printUImmOperand<12>(MI, OpNum, O);
137 }
138 
139 void SystemZInstPrinter::printS16ImmOperand(const MCInst *MI, int OpNum,
140                                             raw_ostream &O) {
141   printSImmOperand<16>(MI, OpNum, O);
142 }
143 
144 void SystemZInstPrinter::printU16ImmOperand(const MCInst *MI, int OpNum,
145                                             raw_ostream &O) {
146   printUImmOperand<16>(MI, OpNum, O);
147 }
148 
149 void SystemZInstPrinter::printS32ImmOperand(const MCInst *MI, int OpNum,
150                                             raw_ostream &O) {
151   printSImmOperand<32>(MI, OpNum, O);
152 }
153 
154 void SystemZInstPrinter::printU32ImmOperand(const MCInst *MI, int OpNum,
155                                             raw_ostream &O) {
156   printUImmOperand<32>(MI, OpNum, O);
157 }
158 
159 void SystemZInstPrinter::printU48ImmOperand(const MCInst *MI, int OpNum,
160                                             raw_ostream &O) {
161   printUImmOperand<48>(MI, OpNum, O);
162 }
163 
164 void SystemZInstPrinter::printPCRelOperand(const MCInst *MI, int OpNum,
165                                            raw_ostream &O) {
166   const MCOperand &MO = MI->getOperand(OpNum);
167   if (MO.isImm()) {
168     O << markup("<imm:") << "0x";
169     O.write_hex(MO.getImm());
170     O << markup(">");
171   } else
172     MO.getExpr()->print(O, &MAI);
173 }
174 
175 void SystemZInstPrinter::printPCRelTLSOperand(const MCInst *MI,
176                                               uint64_t Address, int OpNum,
177                                               raw_ostream &O) {
178   // Output the PC-relative operand.
179   printPCRelOperand(MI, OpNum, O);
180 
181   // Output the TLS marker if present.
182   if ((unsigned)OpNum + 1 < MI->getNumOperands()) {
183     const MCOperand &MO = MI->getOperand(OpNum + 1);
184     const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*MO.getExpr());
185     switch (refExp.getKind()) {
186       case MCSymbolRefExpr::VK_TLSGD:
187         O << ":tls_gdcall:";
188         break;
189       case MCSymbolRefExpr::VK_TLSLDM:
190         O << ":tls_ldcall:";
191         break;
192       default:
193         llvm_unreachable("Unexpected symbol kind");
194     }
195     O << refExp.getSymbol().getName();
196   }
197 }
198 
199 void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum,
200                                       raw_ostream &O) {
201   printOperand(MI->getOperand(OpNum), &MAI, O);
202 }
203 
204 void SystemZInstPrinter::printBDAddrOperand(const MCInst *MI, int OpNum,
205                                             raw_ostream &O) {
206   printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
207                0, O);
208 }
209 
210 void SystemZInstPrinter::printBDXAddrOperand(const MCInst *MI, int OpNum,
211                                              raw_ostream &O) {
212   printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
213                MI->getOperand(OpNum + 2).getReg(), O);
214 }
215 
216 void SystemZInstPrinter::printBDLAddrOperand(const MCInst *MI, int OpNum,
217                                              raw_ostream &O) {
218   unsigned Base = MI->getOperand(OpNum).getReg();
219   const MCOperand &DispMO = MI->getOperand(OpNum + 1);
220   uint64_t Length = MI->getOperand(OpNum + 2).getImm();
221   printOperand(DispMO, &MAI, O);
222   O << '(' << Length;
223   if (Base) {
224     O << ",";
225     printRegName(O, Base);
226   }
227   O << ')';
228 }
229 
230 void SystemZInstPrinter::printBDRAddrOperand(const MCInst *MI, int OpNum,
231                                              raw_ostream &O) {
232   unsigned Base = MI->getOperand(OpNum).getReg();
233   const MCOperand &DispMO = MI->getOperand(OpNum + 1);
234   unsigned Length = MI->getOperand(OpNum + 2).getReg();
235   printOperand(DispMO, &MAI, O);
236   O << "(";
237   printRegName(O, Length);
238   if (Base) {
239     O << ",";
240     printRegName(O, Base);
241   }
242   O << ')';
243 }
244 
245 void SystemZInstPrinter::printBDVAddrOperand(const MCInst *MI, int OpNum,
246                                              raw_ostream &O) {
247   printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1),
248                MI->getOperand(OpNum + 2).getReg(), O);
249 }
250 
251 void SystemZInstPrinter::printCond4Operand(const MCInst *MI, int OpNum,
252                                            raw_ostream &O) {
253   static const char *const CondNames[] = {
254     "o", "h", "nle", "l", "nhe", "lh", "ne",
255     "e", "nlh", "he", "nl", "le", "nh", "no"
256   };
257   uint64_t Imm = MI->getOperand(OpNum).getImm();
258   assert(Imm > 0 && Imm < 15 && "Invalid condition");
259   O << CondNames[Imm - 1];
260 }
261