[MCInstPrinter] Enable MCInstPrinter to change its behavior based on the
[oota-llvm.git] / lib / Target / NVPTX / InstPrinter / NVPTXInstPrinter.cpp
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, const MCSubtargetInfo &STI) {
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 }