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 if (Base)
36 O << ',';
37 }
38 if (Base)
39 printFormattedRegName(MAI, Base, O);
40 O << ')';
41 }
42 }
43
printOperand(const MCOperand & MO,const MCAsmInfo * MAI,raw_ostream & O)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
printFormattedRegName(const MCAsmInfo * MAI,MCRegister Reg,raw_ostream & O) const60 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
printRegName(raw_ostream & O,MCRegister Reg) const72 void SystemZInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) const {
73 printFormattedRegName(&MAI, Reg, O);
74 }
75
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & O)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>
printUImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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>
printSImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)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
printU1ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)99 void SystemZInstPrinter::printU1ImmOperand(const MCInst *MI, int OpNum,
100 raw_ostream &O) {
101 printUImmOperand<1>(MI, OpNum, O);
102 }
103
printU2ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)104 void SystemZInstPrinter::printU2ImmOperand(const MCInst *MI, int OpNum,
105 raw_ostream &O) {
106 printUImmOperand<2>(MI, OpNum, O);
107 }
108
printU3ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)109 void SystemZInstPrinter::printU3ImmOperand(const MCInst *MI, int OpNum,
110 raw_ostream &O) {
111 printUImmOperand<3>(MI, OpNum, O);
112 }
113
printU4ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)114 void SystemZInstPrinter::printU4ImmOperand(const MCInst *MI, int OpNum,
115 raw_ostream &O) {
116 printUImmOperand<4>(MI, OpNum, O);
117 }
118
printU6ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)119 void SystemZInstPrinter::printU6ImmOperand(const MCInst *MI, int OpNum,
120 raw_ostream &O) {
121 printUImmOperand<6>(MI, OpNum, O);
122 }
123
printS8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)124 void SystemZInstPrinter::printS8ImmOperand(const MCInst *MI, int OpNum,
125 raw_ostream &O) {
126 printSImmOperand<8>(MI, OpNum, O);
127 }
128
printU8ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)129 void SystemZInstPrinter::printU8ImmOperand(const MCInst *MI, int OpNum,
130 raw_ostream &O) {
131 printUImmOperand<8>(MI, OpNum, O);
132 }
133
printU12ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)134 void SystemZInstPrinter::printU12ImmOperand(const MCInst *MI, int OpNum,
135 raw_ostream &O) {
136 printUImmOperand<12>(MI, OpNum, O);
137 }
138
printS16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)139 void SystemZInstPrinter::printS16ImmOperand(const MCInst *MI, int OpNum,
140 raw_ostream &O) {
141 printSImmOperand<16>(MI, OpNum, O);
142 }
143
printU16ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)144 void SystemZInstPrinter::printU16ImmOperand(const MCInst *MI, int OpNum,
145 raw_ostream &O) {
146 printUImmOperand<16>(MI, OpNum, O);
147 }
148
printS32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)149 void SystemZInstPrinter::printS32ImmOperand(const MCInst *MI, int OpNum,
150 raw_ostream &O) {
151 printSImmOperand<32>(MI, OpNum, O);
152 }
153
printU32ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)154 void SystemZInstPrinter::printU32ImmOperand(const MCInst *MI, int OpNum,
155 raw_ostream &O) {
156 printUImmOperand<32>(MI, OpNum, O);
157 }
158
printU48ImmOperand(const MCInst * MI,int OpNum,raw_ostream & O)159 void SystemZInstPrinter::printU48ImmOperand(const MCInst *MI, int OpNum,
160 raw_ostream &O) {
161 printUImmOperand<48>(MI, OpNum, O);
162 }
163
printPCRelOperand(const MCInst * MI,int OpNum,raw_ostream & O)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
printPCRelTLSOperand(const MCInst * MI,uint64_t Address,int OpNum,raw_ostream & O)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
printOperand(const MCInst * MI,int OpNum,raw_ostream & O)199 void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum,
200 raw_ostream &O) {
201 printOperand(MI->getOperand(OpNum), &MAI, O);
202 }
203
printBDAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)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
printBDXAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)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
printBDLAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)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
printBDRAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)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
printBDVAddrOperand(const MCInst * MI,int OpNum,raw_ostream & O)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
printCond4Operand(const MCInst * MI,int OpNum,raw_ostream & O)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