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