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 
NVPTXInstPrinter(const MCAsmInfo & MAI,const MCInstrInfo & MII,const MCRegisterInfo & MRI)31 NVPTXInstPrinter::NVPTXInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
32                                    const MCRegisterInfo &MRI)
33     : MCInstPrinter(MAI, MII, MRI) {}
34 
printRegName(raw_ostream & OS,unsigned RegNo) const35 void 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:
42     // This is actually a physical register, so defer to the autogenerated
43     // register printer
44     OS << getRegisterName(RegNo);
45     return;
46   case 1:
47     OS << "%p";
48     break;
49   case 2:
50     OS << "%rs";
51     break;
52   case 3:
53     OS << "%r";
54     break;
55   case 4:
56     OS << "%rd";
57     break;
58   case 5:
59     OS << "%f";
60     break;
61   case 6:
62     OS << "%fd";
63     break;
64   }
65 
66   unsigned VReg = RegNo & 0x0FFFFFFF;
67   OS << VReg;
68 }
69 
printInst(const MCInst * MI,raw_ostream & OS,StringRef Annot,const MCSubtargetInfo & STI)70 void NVPTXInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
71                                  StringRef Annot, const MCSubtargetInfo &STI) {
72   printInstruction(MI, OS);
73 
74   // Next always print the annotation.
75   printAnnotation(OS, Annot);
76 }
77 
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)78 void 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");
88     O << *Op.getExpr();
89   }
90 }
91 
printCvtMode(const MCInst * MI,int OpNum,raw_ostream & O,const char * Modifier)92 void 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 
printCmpMode(const MCInst * MI,int OpNum,raw_ostream & O,const char * Modifier)142 void 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 
printLdStCode(const MCInst * MI,int OpNum,raw_ostream & O,const char * Modifier)215 void 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 
printMemOperand(const MCInst * MI,int OpNum,raw_ostream & O,const char * Modifier)263 void 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 }
278 
printProtoIdent(const MCInst * MI,int OpNum,raw_ostream & O,const char * Modifier)279 void 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 }
287