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