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