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