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