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
printAddress(const MCAsmInfo * MAI,MCRegister Base,const MCOperand & DispMO,MCRegister Index,raw_ostream & O)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
printOperand(const MCOperand & MO,const MCAsmInfo * MAI,raw_ostream & O)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
printRegName(raw_ostream & O,MCRegister Reg)61 void SystemZInstPrinterCommon::printRegName(raw_ostream &O, MCRegister Reg) {
62 printFormattedRegName(&MAI, Reg, O);
63 }
64
65 template <unsigned N>
printUImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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>
printSImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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
printU1ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)91 void SystemZInstPrinterCommon::printU1ImmOperand(const MCInst *MI, int OpNum,
92 raw_ostream &O) {
93 printUImmOperand<1>(MI, OpNum, O);
94 }
95
printU2ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)96 void SystemZInstPrinterCommon::printU2ImmOperand(const MCInst *MI, int OpNum,
97 raw_ostream &O) {
98 printUImmOperand<2>(MI, OpNum, O);
99 }
100
printU3ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)101 void SystemZInstPrinterCommon::printU3ImmOperand(const MCInst *MI, int OpNum,
102 raw_ostream &O) {
103 printUImmOperand<3>(MI, OpNum, O);
104 }
105
printU4ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)106 void SystemZInstPrinterCommon::printU4ImmOperand(const MCInst *MI, int OpNum,
107 raw_ostream &O) {
108 printUImmOperand<4>(MI, OpNum, O);
109 }
110
printS8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)111 void SystemZInstPrinterCommon::printS8ImmOperand(const MCInst *MI, int OpNum,
112 raw_ostream &O) {
113 printSImmOperand<8>(MI, OpNum, O);
114 }
115
printU8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)116 void SystemZInstPrinterCommon::printU8ImmOperand(const MCInst *MI, int OpNum,
117 raw_ostream &O) {
118 printUImmOperand<8>(MI, OpNum, O);
119 }
120
printU12ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)121 void SystemZInstPrinterCommon::printU12ImmOperand(const MCInst *MI, int OpNum,
122 raw_ostream &O) {
123 printUImmOperand<12>(MI, OpNum, O);
124 }
125
printS16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)126 void SystemZInstPrinterCommon::printS16ImmOperand(const MCInst *MI, int OpNum,
127 raw_ostream &O) {
128 printSImmOperand<16>(MI, OpNum, O);
129 }
130
printU16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)131 void SystemZInstPrinterCommon::printU16ImmOperand(const MCInst *MI, int OpNum,
132 raw_ostream &O) {
133 printUImmOperand<16>(MI, OpNum, O);
134 }
135
printS32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)136 void SystemZInstPrinterCommon::printS32ImmOperand(const MCInst *MI, int OpNum,
137 raw_ostream &O) {
138 printSImmOperand<32>(MI, OpNum, O);
139 }
140
printU32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)141 void SystemZInstPrinterCommon::printU32ImmOperand(const MCInst *MI, int OpNum,
142 raw_ostream &O) {
143 printUImmOperand<32>(MI, OpNum, O);
144 }
145
printU48ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)146 void SystemZInstPrinterCommon::printU48ImmOperand(const MCInst *MI, int OpNum,
147 raw_ostream &O) {
148 printUImmOperand<48>(MI, OpNum, O);
149 }
150
printPCRelOperand(const MCInst * MI,uint64_t Address,int OpNum,raw_ostream & O)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
printPCRelTLSOperand(const MCInst * MI,uint64_t Address,int OpNum,raw_ostream & O)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
printOperand(const MCInst * MI,int OpNum,raw_ostream & O)202 void SystemZInstPrinterCommon::printOperand(const MCInst *MI, int OpNum,
203 raw_ostream &O) {
204 printOperand(MI->getOperand(OpNum), &MAI, O);
205 }
206
printBDAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)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
printBDXAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)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
printBDLAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)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
printBDRAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)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
printBDVAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)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
printLXAAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)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
printCond4Operand(const MCInst * MI,int OpNum,raw_ostream & O)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