109467b48Spatrick //===-- NVPTXInstPrinter.cpp - PTX assembly instruction printing ----------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // Print MCInst instructions to .ptx format.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick 
1309467b48Spatrick #include "MCTargetDesc/NVPTXInstPrinter.h"
1409467b48Spatrick #include "MCTargetDesc/NVPTXBaseInfo.h"
1509467b48Spatrick #include "NVPTX.h"
1609467b48Spatrick #include "llvm/MC/MCExpr.h"
1709467b48Spatrick #include "llvm/MC/MCInst.h"
1809467b48Spatrick #include "llvm/MC/MCInstrInfo.h"
1909467b48Spatrick #include "llvm/MC/MCSubtargetInfo.h"
2009467b48Spatrick #include "llvm/MC/MCSymbol.h"
2109467b48Spatrick #include "llvm/Support/ErrorHandling.h"
2209467b48Spatrick #include "llvm/Support/FormattedStream.h"
2309467b48Spatrick #include <cctype>
2409467b48Spatrick using namespace llvm;
2509467b48Spatrick 
2609467b48Spatrick #define DEBUG_TYPE "asm-printer"
2709467b48Spatrick 
2809467b48Spatrick #include "NVPTXGenAsmWriter.inc"
2909467b48Spatrick 
NVPTXInstPrinter(const MCAsmInfo & MAI,const MCInstrInfo & MII,const MCRegisterInfo & MRI)3009467b48Spatrick NVPTXInstPrinter::NVPTXInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
3109467b48Spatrick                                    const MCRegisterInfo &MRI)
3209467b48Spatrick     : MCInstPrinter(MAI, MII, MRI) {}
3309467b48Spatrick 
printRegName(raw_ostream & OS,MCRegister Reg) const34*d415bd75Srobert void NVPTXInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const {
3509467b48Spatrick   // Decode the virtual register
3609467b48Spatrick   // Must be kept in sync with NVPTXAsmPrinter::encodeVirtualRegister
37*d415bd75Srobert   unsigned RCId = (Reg.id() >> 28);
3809467b48Spatrick   switch (RCId) {
3909467b48Spatrick   default: report_fatal_error("Bad virtual register encoding");
4009467b48Spatrick   case 0:
4109467b48Spatrick     // This is actually a physical register, so defer to the autogenerated
4209467b48Spatrick     // register printer
43*d415bd75Srobert     OS << getRegisterName(Reg);
4409467b48Spatrick     return;
4509467b48Spatrick   case 1:
4609467b48Spatrick     OS << "%p";
4709467b48Spatrick     break;
4809467b48Spatrick   case 2:
4909467b48Spatrick     OS << "%rs";
5009467b48Spatrick     break;
5109467b48Spatrick   case 3:
5209467b48Spatrick     OS << "%r";
5309467b48Spatrick     break;
5409467b48Spatrick   case 4:
5509467b48Spatrick     OS << "%rd";
5609467b48Spatrick     break;
5709467b48Spatrick   case 5:
5809467b48Spatrick     OS << "%f";
5909467b48Spatrick     break;
6009467b48Spatrick   case 6:
6109467b48Spatrick     OS << "%fd";
6209467b48Spatrick     break;
6309467b48Spatrick   case 7:
6409467b48Spatrick     OS << "%h";
6509467b48Spatrick     break;
6609467b48Spatrick   case 8:
6709467b48Spatrick     OS << "%hh";
6809467b48Spatrick     break;
6909467b48Spatrick   }
7009467b48Spatrick 
71*d415bd75Srobert   unsigned VReg = Reg.id() & 0x0FFFFFFF;
7209467b48Spatrick   OS << VReg;
7309467b48Spatrick }
7409467b48Spatrick 
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & OS)7509467b48Spatrick void NVPTXInstPrinter::printInst(const MCInst *MI, uint64_t Address,
7609467b48Spatrick                                  StringRef Annot, const MCSubtargetInfo &STI,
7709467b48Spatrick                                  raw_ostream &OS) {
7809467b48Spatrick   printInstruction(MI, Address, OS);
7909467b48Spatrick 
8009467b48Spatrick   // Next always print the annotation.
8109467b48Spatrick   printAnnotation(OS, Annot);
8209467b48Spatrick }
8309467b48Spatrick 
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)8409467b48Spatrick void NVPTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
8509467b48Spatrick                                     raw_ostream &O) {
8609467b48Spatrick   const MCOperand &Op = MI->getOperand(OpNo);
8709467b48Spatrick   if (Op.isReg()) {
8809467b48Spatrick     unsigned Reg = Op.getReg();
8909467b48Spatrick     printRegName(O, Reg);
9009467b48Spatrick   } else if (Op.isImm()) {
9109467b48Spatrick     O << markup("<imm:") << formatImm(Op.getImm()) << markup(">");
9209467b48Spatrick   } else {
9309467b48Spatrick     assert(Op.isExpr() && "Unknown operand kind in printOperand");
9409467b48Spatrick     Op.getExpr()->print(O, &MAI);
9509467b48Spatrick   }
9609467b48Spatrick }
9709467b48Spatrick 
printCvtMode(const MCInst * MI,int OpNum,raw_ostream & O,const char * Modifier)9809467b48Spatrick void NVPTXInstPrinter::printCvtMode(const MCInst *MI, int OpNum, raw_ostream &O,
9909467b48Spatrick                                     const char *Modifier) {
10009467b48Spatrick   const MCOperand &MO = MI->getOperand(OpNum);
10109467b48Spatrick   int64_t Imm = MO.getImm();
10209467b48Spatrick 
10309467b48Spatrick   if (strcmp(Modifier, "ftz") == 0) {
10409467b48Spatrick     // FTZ flag
10509467b48Spatrick     if (Imm & NVPTX::PTXCvtMode::FTZ_FLAG)
10609467b48Spatrick       O << ".ftz";
10709467b48Spatrick   } else if (strcmp(Modifier, "sat") == 0) {
10809467b48Spatrick     // SAT flag
10909467b48Spatrick     if (Imm & NVPTX::PTXCvtMode::SAT_FLAG)
11009467b48Spatrick       O << ".sat";
111*d415bd75Srobert   } else if (strcmp(Modifier, "relu") == 0) {
112*d415bd75Srobert     // RELU flag
113*d415bd75Srobert     if (Imm & NVPTX::PTXCvtMode::RELU_FLAG)
114*d415bd75Srobert       O << ".relu";
11509467b48Spatrick   } else if (strcmp(Modifier, "base") == 0) {
11609467b48Spatrick     // Default operand
11709467b48Spatrick     switch (Imm & NVPTX::PTXCvtMode::BASE_MASK) {
11809467b48Spatrick     default:
11909467b48Spatrick       return;
12009467b48Spatrick     case NVPTX::PTXCvtMode::NONE:
12109467b48Spatrick       break;
12209467b48Spatrick     case NVPTX::PTXCvtMode::RNI:
12309467b48Spatrick       O << ".rni";
12409467b48Spatrick       break;
12509467b48Spatrick     case NVPTX::PTXCvtMode::RZI:
12609467b48Spatrick       O << ".rzi";
12709467b48Spatrick       break;
12809467b48Spatrick     case NVPTX::PTXCvtMode::RMI:
12909467b48Spatrick       O << ".rmi";
13009467b48Spatrick       break;
13109467b48Spatrick     case NVPTX::PTXCvtMode::RPI:
13209467b48Spatrick       O << ".rpi";
13309467b48Spatrick       break;
13409467b48Spatrick     case NVPTX::PTXCvtMode::RN:
13509467b48Spatrick       O << ".rn";
13609467b48Spatrick       break;
13709467b48Spatrick     case NVPTX::PTXCvtMode::RZ:
13809467b48Spatrick       O << ".rz";
13909467b48Spatrick       break;
14009467b48Spatrick     case NVPTX::PTXCvtMode::RM:
14109467b48Spatrick       O << ".rm";
14209467b48Spatrick       break;
14309467b48Spatrick     case NVPTX::PTXCvtMode::RP:
14409467b48Spatrick       O << ".rp";
14509467b48Spatrick       break;
146*d415bd75Srobert     case NVPTX::PTXCvtMode::RNA:
147*d415bd75Srobert       O << ".rna";
148*d415bd75Srobert       break;
14909467b48Spatrick     }
15009467b48Spatrick   } else {
15109467b48Spatrick     llvm_unreachable("Invalid conversion modifier");
15209467b48Spatrick   }
15309467b48Spatrick }
15409467b48Spatrick 
printCmpMode(const MCInst * MI,int OpNum,raw_ostream & O,const char * Modifier)15509467b48Spatrick void NVPTXInstPrinter::printCmpMode(const MCInst *MI, int OpNum, raw_ostream &O,
15609467b48Spatrick                                     const char *Modifier) {
15709467b48Spatrick   const MCOperand &MO = MI->getOperand(OpNum);
15809467b48Spatrick   int64_t Imm = MO.getImm();
15909467b48Spatrick 
16009467b48Spatrick   if (strcmp(Modifier, "ftz") == 0) {
16109467b48Spatrick     // FTZ flag
16209467b48Spatrick     if (Imm & NVPTX::PTXCmpMode::FTZ_FLAG)
16309467b48Spatrick       O << ".ftz";
16409467b48Spatrick   } else if (strcmp(Modifier, "base") == 0) {
16509467b48Spatrick     switch (Imm & NVPTX::PTXCmpMode::BASE_MASK) {
16609467b48Spatrick     default:
16709467b48Spatrick       return;
16809467b48Spatrick     case NVPTX::PTXCmpMode::EQ:
16909467b48Spatrick       O << ".eq";
17009467b48Spatrick       break;
17109467b48Spatrick     case NVPTX::PTXCmpMode::NE:
17209467b48Spatrick       O << ".ne";
17309467b48Spatrick       break;
17409467b48Spatrick     case NVPTX::PTXCmpMode::LT:
17509467b48Spatrick       O << ".lt";
17609467b48Spatrick       break;
17709467b48Spatrick     case NVPTX::PTXCmpMode::LE:
17809467b48Spatrick       O << ".le";
17909467b48Spatrick       break;
18009467b48Spatrick     case NVPTX::PTXCmpMode::GT:
18109467b48Spatrick       O << ".gt";
18209467b48Spatrick       break;
18309467b48Spatrick     case NVPTX::PTXCmpMode::GE:
18409467b48Spatrick       O << ".ge";
18509467b48Spatrick       break;
18609467b48Spatrick     case NVPTX::PTXCmpMode::LO:
18709467b48Spatrick       O << ".lo";
18809467b48Spatrick       break;
18909467b48Spatrick     case NVPTX::PTXCmpMode::LS:
19009467b48Spatrick       O << ".ls";
19109467b48Spatrick       break;
19209467b48Spatrick     case NVPTX::PTXCmpMode::HI:
19309467b48Spatrick       O << ".hi";
19409467b48Spatrick       break;
19509467b48Spatrick     case NVPTX::PTXCmpMode::HS:
19609467b48Spatrick       O << ".hs";
19709467b48Spatrick       break;
19809467b48Spatrick     case NVPTX::PTXCmpMode::EQU:
19909467b48Spatrick       O << ".equ";
20009467b48Spatrick       break;
20109467b48Spatrick     case NVPTX::PTXCmpMode::NEU:
20209467b48Spatrick       O << ".neu";
20309467b48Spatrick       break;
20409467b48Spatrick     case NVPTX::PTXCmpMode::LTU:
20509467b48Spatrick       O << ".ltu";
20609467b48Spatrick       break;
20709467b48Spatrick     case NVPTX::PTXCmpMode::LEU:
20809467b48Spatrick       O << ".leu";
20909467b48Spatrick       break;
21009467b48Spatrick     case NVPTX::PTXCmpMode::GTU:
21109467b48Spatrick       O << ".gtu";
21209467b48Spatrick       break;
21309467b48Spatrick     case NVPTX::PTXCmpMode::GEU:
21409467b48Spatrick       O << ".geu";
21509467b48Spatrick       break;
21609467b48Spatrick     case NVPTX::PTXCmpMode::NUM:
21709467b48Spatrick       O << ".num";
21809467b48Spatrick       break;
21909467b48Spatrick     case NVPTX::PTXCmpMode::NotANumber:
22009467b48Spatrick       O << ".nan";
22109467b48Spatrick       break;
22209467b48Spatrick     }
22309467b48Spatrick   } else {
22409467b48Spatrick     llvm_unreachable("Empty Modifier");
22509467b48Spatrick   }
22609467b48Spatrick }
22709467b48Spatrick 
printLdStCode(const MCInst * MI,int OpNum,raw_ostream & O,const char * Modifier)22809467b48Spatrick void NVPTXInstPrinter::printLdStCode(const MCInst *MI, int OpNum,
22909467b48Spatrick                                      raw_ostream &O, const char *Modifier) {
23009467b48Spatrick   if (Modifier) {
23109467b48Spatrick     const MCOperand &MO = MI->getOperand(OpNum);
23209467b48Spatrick     int Imm = (int) MO.getImm();
23309467b48Spatrick     if (!strcmp(Modifier, "volatile")) {
23409467b48Spatrick       if (Imm)
23509467b48Spatrick         O << ".volatile";
23609467b48Spatrick     } else if (!strcmp(Modifier, "addsp")) {
23709467b48Spatrick       switch (Imm) {
23809467b48Spatrick       case NVPTX::PTXLdStInstCode::GLOBAL:
23909467b48Spatrick         O << ".global";
24009467b48Spatrick         break;
24109467b48Spatrick       case NVPTX::PTXLdStInstCode::SHARED:
24209467b48Spatrick         O << ".shared";
24309467b48Spatrick         break;
24409467b48Spatrick       case NVPTX::PTXLdStInstCode::LOCAL:
24509467b48Spatrick         O << ".local";
24609467b48Spatrick         break;
24709467b48Spatrick       case NVPTX::PTXLdStInstCode::PARAM:
24809467b48Spatrick         O << ".param";
24909467b48Spatrick         break;
25009467b48Spatrick       case NVPTX::PTXLdStInstCode::CONSTANT:
25109467b48Spatrick         O << ".const";
25209467b48Spatrick         break;
25309467b48Spatrick       case NVPTX::PTXLdStInstCode::GENERIC:
25409467b48Spatrick         break;
25509467b48Spatrick       default:
25609467b48Spatrick         llvm_unreachable("Wrong Address Space");
25709467b48Spatrick       }
25809467b48Spatrick     } else if (!strcmp(Modifier, "sign")) {
25909467b48Spatrick       if (Imm == NVPTX::PTXLdStInstCode::Signed)
26009467b48Spatrick         O << "s";
26109467b48Spatrick       else if (Imm == NVPTX::PTXLdStInstCode::Unsigned)
26209467b48Spatrick         O << "u";
26309467b48Spatrick       else if (Imm == NVPTX::PTXLdStInstCode::Untyped)
26409467b48Spatrick         O << "b";
26509467b48Spatrick       else if (Imm == NVPTX::PTXLdStInstCode::Float)
26609467b48Spatrick         O << "f";
26709467b48Spatrick       else
26809467b48Spatrick         llvm_unreachable("Unknown register type");
26909467b48Spatrick     } else if (!strcmp(Modifier, "vec")) {
27009467b48Spatrick       if (Imm == NVPTX::PTXLdStInstCode::V2)
27109467b48Spatrick         O << ".v2";
27209467b48Spatrick       else if (Imm == NVPTX::PTXLdStInstCode::V4)
27309467b48Spatrick         O << ".v4";
27409467b48Spatrick     } else
27509467b48Spatrick       llvm_unreachable("Unknown Modifier");
27609467b48Spatrick   } else
27709467b48Spatrick     llvm_unreachable("Empty Modifier");
27809467b48Spatrick }
27909467b48Spatrick 
printMmaCode(const MCInst * MI,int OpNum,raw_ostream & O,const char * Modifier)28009467b48Spatrick void NVPTXInstPrinter::printMmaCode(const MCInst *MI, int OpNum, raw_ostream &O,
28109467b48Spatrick                                     const char *Modifier) {
28209467b48Spatrick   const MCOperand &MO = MI->getOperand(OpNum);
28309467b48Spatrick   int Imm = (int)MO.getImm();
28409467b48Spatrick   if (Modifier == nullptr || strcmp(Modifier, "version") == 0) {
28509467b48Spatrick     O << Imm; // Just print out PTX version
28609467b48Spatrick   } else if (strcmp(Modifier, "aligned") == 0) {
28709467b48Spatrick     // PTX63 requires '.aligned' in the name of the instruction.
28809467b48Spatrick     if (Imm >= 63)
28909467b48Spatrick       O << ".aligned";
29009467b48Spatrick   } else
29109467b48Spatrick     llvm_unreachable("Unknown Modifier");
29209467b48Spatrick }
29309467b48Spatrick 
printMemOperand(const MCInst * MI,int OpNum,raw_ostream & O,const char * Modifier)29409467b48Spatrick void NVPTXInstPrinter::printMemOperand(const MCInst *MI, int OpNum,
29509467b48Spatrick                                        raw_ostream &O, const char *Modifier) {
29609467b48Spatrick   printOperand(MI, OpNum, O);
29709467b48Spatrick 
29809467b48Spatrick   if (Modifier && !strcmp(Modifier, "add")) {
29909467b48Spatrick     O << ", ";
30009467b48Spatrick     printOperand(MI, OpNum + 1, O);
30109467b48Spatrick   } else {
30209467b48Spatrick     if (MI->getOperand(OpNum + 1).isImm() &&
30309467b48Spatrick         MI->getOperand(OpNum + 1).getImm() == 0)
30409467b48Spatrick       return; // don't print ',0' or '+0'
30509467b48Spatrick     O << "+";
30609467b48Spatrick     printOperand(MI, OpNum + 1, O);
30709467b48Spatrick   }
30809467b48Spatrick }
30909467b48Spatrick 
printProtoIdent(const MCInst * MI,int OpNum,raw_ostream & O,const char * Modifier)31009467b48Spatrick void NVPTXInstPrinter::printProtoIdent(const MCInst *MI, int OpNum,
31109467b48Spatrick                                        raw_ostream &O, const char *Modifier) {
31209467b48Spatrick   const MCOperand &Op = MI->getOperand(OpNum);
31309467b48Spatrick   assert(Op.isExpr() && "Call prototype is not an MCExpr?");
31409467b48Spatrick   const MCExpr *Expr = Op.getExpr();
31509467b48Spatrick   const MCSymbol &Sym = cast<MCSymbolRefExpr>(Expr)->getSymbol();
31609467b48Spatrick   O << Sym.getName();
31709467b48Spatrick }
318