]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | //===-- NVPTXInstPrinter.cpp - PTX assembly instruction printing ----------===// |
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 | // Print MCInst instructions to .ptx format. | |
11 | // | |
12 | //===----------------------------------------------------------------------===// | |
13 | ||
14 | #include "InstPrinter/NVPTXInstPrinter.h" | |
15 | #include "MCTargetDesc/NVPTXBaseInfo.h" | |
16 | #include "NVPTX.h" | |
17 | #include "llvm/MC/MCExpr.h" | |
18 | #include "llvm/MC/MCInst.h" | |
19 | #include "llvm/MC/MCInstrInfo.h" | |
20 | #include "llvm/MC/MCSubtargetInfo.h" | |
21 | #include "llvm/MC/MCSymbol.h" | |
22 | #include "llvm/Support/ErrorHandling.h" | |
23 | #include "llvm/Support/FormattedStream.h" | |
24 | #include <cctype> | |
25 | using namespace llvm; | |
26 | ||
27 | #define DEBUG_TYPE "asm-printer" | |
28 | ||
29 | #include "NVPTXGenAsmWriter.inc" | |
30 | ||
31 | ||
32 | NVPTXInstPrinter::NVPTXInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, | |
33 | const MCRegisterInfo &MRI, | |
34 | const MCSubtargetInfo &STI) | |
35 | : MCInstPrinter(MAI, MII, MRI) { | |
36 | setAvailableFeatures(STI.getFeatureBits()); | |
37 | } | |
38 | ||
39 | void NVPTXInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { | |
40 | // Decode the virtual register | |
41 | // Must be kept in sync with NVPTXAsmPrinter::encodeVirtualRegister | |
42 | unsigned RCId = (RegNo >> 28); | |
43 | switch (RCId) { | |
44 | default: report_fatal_error("Bad virtual register encoding"); | |
45 | case 0: | |
46 | // This is actually a physical register, so defer to the autogenerated | |
47 | // register printer | |
48 | OS << getRegisterName(RegNo); | |
49 | return; | |
50 | case 1: | |
51 | OS << "%p"; | |
52 | break; | |
53 | case 2: | |
54 | OS << "%rs"; | |
55 | break; | |
56 | case 3: | |
57 | OS << "%r"; | |
58 | break; | |
59 | case 4: | |
60 | OS << "%rd"; | |
61 | break; | |
62 | case 5: | |
63 | OS << "%f"; | |
64 | break; | |
65 | case 6: | |
66 | OS << "%fd"; | |
67 | break; | |
68 | } | |
69 | ||
70 | unsigned VReg = RegNo & 0x0FFFFFFF; | |
71 | OS << VReg; | |
72 | } | |
73 | ||
74 | void NVPTXInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, | |
75 | StringRef Annot) { | |
76 | printInstruction(MI, OS); | |
77 | ||
78 | // Next always print the annotation. | |
79 | printAnnotation(OS, Annot); | |
80 | } | |
81 | ||
82 | void NVPTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, | |
83 | raw_ostream &O) { | |
84 | const MCOperand &Op = MI->getOperand(OpNo); | |
85 | if (Op.isReg()) { | |
86 | unsigned Reg = Op.getReg(); | |
87 | printRegName(O, Reg); | |
88 | } else if (Op.isImm()) { | |
89 | O << markup("<imm:") << formatImm(Op.getImm()) << markup(">"); | |
90 | } else { | |
91 | assert(Op.isExpr() && "Unknown operand kind in printOperand"); | |
92 | O << *Op.getExpr(); | |
93 | } | |
94 | } | |
95 | ||
96 | void NVPTXInstPrinter::printCvtMode(const MCInst *MI, int OpNum, raw_ostream &O, | |
97 | const char *Modifier) { | |
98 | const MCOperand &MO = MI->getOperand(OpNum); | |
99 | int64_t Imm = MO.getImm(); | |
100 | ||
101 | if (strcmp(Modifier, "ftz") == 0) { | |
102 | // FTZ flag | |
103 | if (Imm & NVPTX::PTXCvtMode::FTZ_FLAG) | |
104 | O << ".ftz"; | |
105 | } else if (strcmp(Modifier, "sat") == 0) { | |
106 | // SAT flag | |
107 | if (Imm & NVPTX::PTXCvtMode::SAT_FLAG) | |
108 | O << ".sat"; | |
109 | } else if (strcmp(Modifier, "base") == 0) { | |
110 | // Default operand | |
111 | switch (Imm & NVPTX::PTXCvtMode::BASE_MASK) { | |
112 | default: | |
113 | return; | |
114 | case NVPTX::PTXCvtMode::NONE: | |
115 | break; | |
116 | case NVPTX::PTXCvtMode::RNI: | |
117 | O << ".rni"; | |
118 | break; | |
119 | case NVPTX::PTXCvtMode::RZI: | |
120 | O << ".rzi"; | |
121 | break; | |
122 | case NVPTX::PTXCvtMode::RMI: | |
123 | O << ".rmi"; | |
124 | break; | |
125 | case NVPTX::PTXCvtMode::RPI: | |
126 | O << ".rpi"; | |
127 | break; | |
128 | case NVPTX::PTXCvtMode::RN: | |
129 | O << ".rn"; | |
130 | break; | |
131 | case NVPTX::PTXCvtMode::RZ: | |
132 | O << ".rz"; | |
133 | break; | |
134 | case NVPTX::PTXCvtMode::RM: | |
135 | O << ".rm"; | |
136 | break; | |
137 | case NVPTX::PTXCvtMode::RP: | |
138 | O << ".rp"; | |
139 | break; | |
140 | } | |
141 | } else { | |
142 | llvm_unreachable("Invalid conversion modifier"); | |
143 | } | |
144 | } | |
145 | ||
146 | void NVPTXInstPrinter::printCmpMode(const MCInst *MI, int OpNum, raw_ostream &O, | |
147 | const char *Modifier) { | |
148 | const MCOperand &MO = MI->getOperand(OpNum); | |
149 | int64_t Imm = MO.getImm(); | |
150 | ||
151 | if (strcmp(Modifier, "ftz") == 0) { | |
152 | // FTZ flag | |
153 | if (Imm & NVPTX::PTXCmpMode::FTZ_FLAG) | |
154 | O << ".ftz"; | |
155 | } else if (strcmp(Modifier, "base") == 0) { | |
156 | switch (Imm & NVPTX::PTXCmpMode::BASE_MASK) { | |
157 | default: | |
158 | return; | |
159 | case NVPTX::PTXCmpMode::EQ: | |
160 | O << ".eq"; | |
161 | break; | |
162 | case NVPTX::PTXCmpMode::NE: | |
163 | O << ".ne"; | |
164 | break; | |
165 | case NVPTX::PTXCmpMode::LT: | |
166 | O << ".lt"; | |
167 | break; | |
168 | case NVPTX::PTXCmpMode::LE: | |
169 | O << ".le"; | |
170 | break; | |
171 | case NVPTX::PTXCmpMode::GT: | |
172 | O << ".gt"; | |
173 | break; | |
174 | case NVPTX::PTXCmpMode::GE: | |
175 | O << ".ge"; | |
176 | break; | |
177 | case NVPTX::PTXCmpMode::LO: | |
178 | O << ".lo"; | |
179 | break; | |
180 | case NVPTX::PTXCmpMode::LS: | |
181 | O << ".ls"; | |
182 | break; | |
183 | case NVPTX::PTXCmpMode::HI: | |
184 | O << ".hi"; | |
185 | break; | |
186 | case NVPTX::PTXCmpMode::HS: | |
187 | O << ".hs"; | |
188 | break; | |
189 | case NVPTX::PTXCmpMode::EQU: | |
190 | O << ".equ"; | |
191 | break; | |
192 | case NVPTX::PTXCmpMode::NEU: | |
193 | O << ".neu"; | |
194 | break; | |
195 | case NVPTX::PTXCmpMode::LTU: | |
196 | O << ".ltu"; | |
197 | break; | |
198 | case NVPTX::PTXCmpMode::LEU: | |
199 | O << ".leu"; | |
200 | break; | |
201 | case NVPTX::PTXCmpMode::GTU: | |
202 | O << ".gtu"; | |
203 | break; | |
204 | case NVPTX::PTXCmpMode::GEU: | |
205 | O << ".geu"; | |
206 | break; | |
207 | case NVPTX::PTXCmpMode::NUM: | |
208 | O << ".num"; | |
209 | break; | |
210 | case NVPTX::PTXCmpMode::NotANumber: | |
211 | O << ".nan"; | |
212 | break; | |
213 | } | |
214 | } else { | |
215 | llvm_unreachable("Empty Modifier"); | |
216 | } | |
217 | } | |
218 | ||
219 | void NVPTXInstPrinter::printLdStCode(const MCInst *MI, int OpNum, | |
220 | raw_ostream &O, const char *Modifier) { | |
221 | if (Modifier) { | |
222 | const MCOperand &MO = MI->getOperand(OpNum); | |
223 | int Imm = (int) MO.getImm(); | |
224 | if (!strcmp(Modifier, "volatile")) { | |
225 | if (Imm) | |
226 | O << ".volatile"; | |
227 | } else if (!strcmp(Modifier, "addsp")) { | |
228 | switch (Imm) { | |
229 | case NVPTX::PTXLdStInstCode::GLOBAL: | |
230 | O << ".global"; | |
231 | break; | |
232 | case NVPTX::PTXLdStInstCode::SHARED: | |
233 | O << ".shared"; | |
234 | break; | |
235 | case NVPTX::PTXLdStInstCode::LOCAL: | |
236 | O << ".local"; | |
237 | break; | |
238 | case NVPTX::PTXLdStInstCode::PARAM: | |
239 | O << ".param"; | |
240 | break; | |
241 | case NVPTX::PTXLdStInstCode::CONSTANT: | |
242 | O << ".const"; | |
243 | break; | |
244 | case NVPTX::PTXLdStInstCode::GENERIC: | |
245 | break; | |
246 | default: | |
247 | llvm_unreachable("Wrong Address Space"); | |
248 | } | |
249 | } else if (!strcmp(Modifier, "sign")) { | |
250 | if (Imm == NVPTX::PTXLdStInstCode::Signed) | |
251 | O << "s"; | |
252 | else if (Imm == NVPTX::PTXLdStInstCode::Unsigned) | |
253 | O << "u"; | |
254 | else | |
255 | O << "f"; | |
256 | } else if (!strcmp(Modifier, "vec")) { | |
257 | if (Imm == NVPTX::PTXLdStInstCode::V2) | |
258 | O << ".v2"; | |
259 | else if (Imm == NVPTX::PTXLdStInstCode::V4) | |
260 | O << ".v4"; | |
261 | } else | |
262 | llvm_unreachable("Unknown Modifier"); | |
263 | } else | |
264 | llvm_unreachable("Empty Modifier"); | |
265 | } | |
266 | ||
267 | void NVPTXInstPrinter::printMemOperand(const MCInst *MI, int OpNum, | |
268 | raw_ostream &O, const char *Modifier) { | |
269 | printOperand(MI, OpNum, O); | |
270 | ||
271 | if (Modifier && !strcmp(Modifier, "add")) { | |
272 | O << ", "; | |
273 | printOperand(MI, OpNum + 1, O); | |
274 | } else { | |
275 | if (MI->getOperand(OpNum + 1).isImm() && | |
276 | MI->getOperand(OpNum + 1).getImm() == 0) | |
277 | return; // don't print ',0' or '+0' | |
278 | O << "+"; | |
279 | printOperand(MI, OpNum + 1, O); | |
280 | } | |
281 | } | |
282 | ||
283 | void NVPTXInstPrinter::printProtoIdent(const MCInst *MI, int OpNum, | |
284 | raw_ostream &O, const char *Modifier) { | |
285 | const MCOperand &Op = MI->getOperand(OpNum); | |
286 | assert(Op.isExpr() && "Call prototype is not an MCExpr?"); | |
287 | const MCExpr *Expr = Op.getExpr(); | |
288 | const MCSymbol &Sym = cast<MCSymbolRefExpr>(Expr)->getSymbol(); | |
289 | O << Sym.getName(); | |
290 | } |