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