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