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