xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXInstPrinter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- NVPTXInstPrinter.cpp - PTX assembly instruction printing ----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Print MCInst instructions to .ptx format.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "MCTargetDesc/NVPTXInstPrinter.h"
140b57cec5SDimitry Andric #include "MCTargetDesc/NVPTXBaseInfo.h"
150b57cec5SDimitry Andric #include "NVPTX.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
210b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
220b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h"
230b57cec5SDimitry Andric #include <cctype>
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric #define DEBUG_TYPE "asm-printer"
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric #include "NVPTXGenAsmWriter.inc"
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric NVPTXInstPrinter::NVPTXInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
310b57cec5SDimitry Andric                                    const MCRegisterInfo &MRI)
320b57cec5SDimitry Andric     : MCInstPrinter(MAI, MII, MRI) {}
330b57cec5SDimitry Andric 
34bdd1243dSDimitry Andric void NVPTXInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const {
350b57cec5SDimitry Andric   // Decode the virtual register
360b57cec5SDimitry Andric   // Must be kept in sync with NVPTXAsmPrinter::encodeVirtualRegister
37bdd1243dSDimitry Andric   unsigned RCId = (Reg.id() >> 28);
380b57cec5SDimitry Andric   switch (RCId) {
390b57cec5SDimitry Andric   default: report_fatal_error("Bad virtual register encoding");
400b57cec5SDimitry Andric   case 0:
410b57cec5SDimitry Andric     // This is actually a physical register, so defer to the autogenerated
420b57cec5SDimitry Andric     // register printer
43bdd1243dSDimitry Andric     OS << getRegisterName(Reg);
440b57cec5SDimitry Andric     return;
450b57cec5SDimitry Andric   case 1:
460b57cec5SDimitry Andric     OS << "%p";
470b57cec5SDimitry Andric     break;
480b57cec5SDimitry Andric   case 2:
490b57cec5SDimitry Andric     OS << "%rs";
500b57cec5SDimitry Andric     break;
510b57cec5SDimitry Andric   case 3:
520b57cec5SDimitry Andric     OS << "%r";
530b57cec5SDimitry Andric     break;
540b57cec5SDimitry Andric   case 4:
550b57cec5SDimitry Andric     OS << "%rd";
560b57cec5SDimitry Andric     break;
570b57cec5SDimitry Andric   case 5:
580b57cec5SDimitry Andric     OS << "%f";
590b57cec5SDimitry Andric     break;
600b57cec5SDimitry Andric   case 6:
610b57cec5SDimitry Andric     OS << "%fd";
620b57cec5SDimitry Andric     break;
63*0fca6ea1SDimitry Andric   case 7:
64*0fca6ea1SDimitry Andric     OS << "%rq";
65*0fca6ea1SDimitry Andric     break;
660b57cec5SDimitry Andric   }
670b57cec5SDimitry Andric 
68bdd1243dSDimitry Andric   unsigned VReg = Reg.id() & 0x0FFFFFFF;
690b57cec5SDimitry Andric   OS << VReg;
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric 
72480093f4SDimitry Andric void NVPTXInstPrinter::printInst(const MCInst *MI, uint64_t Address,
73480093f4SDimitry Andric                                  StringRef Annot, const MCSubtargetInfo &STI,
74480093f4SDimitry Andric                                  raw_ostream &OS) {
75480093f4SDimitry Andric   printInstruction(MI, Address, OS);
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   // Next always print the annotation.
780b57cec5SDimitry Andric   printAnnotation(OS, Annot);
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric void NVPTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
820b57cec5SDimitry Andric                                     raw_ostream &O) {
830b57cec5SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNo);
840b57cec5SDimitry Andric   if (Op.isReg()) {
850b57cec5SDimitry Andric     unsigned Reg = Op.getReg();
860b57cec5SDimitry Andric     printRegName(O, Reg);
870b57cec5SDimitry Andric   } else if (Op.isImm()) {
885f757f3fSDimitry Andric     markup(O, Markup::Immediate) << formatImm(Op.getImm());
890b57cec5SDimitry Andric   } else {
900b57cec5SDimitry Andric     assert(Op.isExpr() && "Unknown operand kind in printOperand");
910b57cec5SDimitry Andric     Op.getExpr()->print(O, &MAI);
920b57cec5SDimitry Andric   }
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric void NVPTXInstPrinter::printCvtMode(const MCInst *MI, int OpNum, raw_ostream &O,
960b57cec5SDimitry Andric                                     const char *Modifier) {
970b57cec5SDimitry Andric   const MCOperand &MO = MI->getOperand(OpNum);
980b57cec5SDimitry Andric   int64_t Imm = MO.getImm();
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   if (strcmp(Modifier, "ftz") == 0) {
1010b57cec5SDimitry Andric     // FTZ flag
1020b57cec5SDimitry Andric     if (Imm & NVPTX::PTXCvtMode::FTZ_FLAG)
1030b57cec5SDimitry Andric       O << ".ftz";
1040b57cec5SDimitry Andric   } else if (strcmp(Modifier, "sat") == 0) {
1050b57cec5SDimitry Andric     // SAT flag
1060b57cec5SDimitry Andric     if (Imm & NVPTX::PTXCvtMode::SAT_FLAG)
1070b57cec5SDimitry Andric       O << ".sat";
10804eeddc0SDimitry Andric   } else if (strcmp(Modifier, "relu") == 0) {
10904eeddc0SDimitry Andric     // RELU flag
11004eeddc0SDimitry Andric     if (Imm & NVPTX::PTXCvtMode::RELU_FLAG)
11104eeddc0SDimitry Andric       O << ".relu";
1120b57cec5SDimitry Andric   } else if (strcmp(Modifier, "base") == 0) {
1130b57cec5SDimitry Andric     // Default operand
1140b57cec5SDimitry Andric     switch (Imm & NVPTX::PTXCvtMode::BASE_MASK) {
1150b57cec5SDimitry Andric     default:
1160b57cec5SDimitry Andric       return;
1170b57cec5SDimitry Andric     case NVPTX::PTXCvtMode::NONE:
1180b57cec5SDimitry Andric       break;
1190b57cec5SDimitry Andric     case NVPTX::PTXCvtMode::RNI:
1200b57cec5SDimitry Andric       O << ".rni";
1210b57cec5SDimitry Andric       break;
1220b57cec5SDimitry Andric     case NVPTX::PTXCvtMode::RZI:
1230b57cec5SDimitry Andric       O << ".rzi";
1240b57cec5SDimitry Andric       break;
1250b57cec5SDimitry Andric     case NVPTX::PTXCvtMode::RMI:
1260b57cec5SDimitry Andric       O << ".rmi";
1270b57cec5SDimitry Andric       break;
1280b57cec5SDimitry Andric     case NVPTX::PTXCvtMode::RPI:
1290b57cec5SDimitry Andric       O << ".rpi";
1300b57cec5SDimitry Andric       break;
1310b57cec5SDimitry Andric     case NVPTX::PTXCvtMode::RN:
1320b57cec5SDimitry Andric       O << ".rn";
1330b57cec5SDimitry Andric       break;
1340b57cec5SDimitry Andric     case NVPTX::PTXCvtMode::RZ:
1350b57cec5SDimitry Andric       O << ".rz";
1360b57cec5SDimitry Andric       break;
1370b57cec5SDimitry Andric     case NVPTX::PTXCvtMode::RM:
1380b57cec5SDimitry Andric       O << ".rm";
1390b57cec5SDimitry Andric       break;
1400b57cec5SDimitry Andric     case NVPTX::PTXCvtMode::RP:
1410b57cec5SDimitry Andric       O << ".rp";
1420b57cec5SDimitry Andric       break;
14304eeddc0SDimitry Andric     case NVPTX::PTXCvtMode::RNA:
14404eeddc0SDimitry Andric       O << ".rna";
14504eeddc0SDimitry Andric       break;
1460b57cec5SDimitry Andric     }
1470b57cec5SDimitry Andric   } else {
1480b57cec5SDimitry Andric     llvm_unreachable("Invalid conversion modifier");
1490b57cec5SDimitry Andric   }
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric void NVPTXInstPrinter::printCmpMode(const MCInst *MI, int OpNum, raw_ostream &O,
1530b57cec5SDimitry Andric                                     const char *Modifier) {
1540b57cec5SDimitry Andric   const MCOperand &MO = MI->getOperand(OpNum);
1550b57cec5SDimitry Andric   int64_t Imm = MO.getImm();
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric   if (strcmp(Modifier, "ftz") == 0) {
1580b57cec5SDimitry Andric     // FTZ flag
1590b57cec5SDimitry Andric     if (Imm & NVPTX::PTXCmpMode::FTZ_FLAG)
1600b57cec5SDimitry Andric       O << ".ftz";
1610b57cec5SDimitry Andric   } else if (strcmp(Modifier, "base") == 0) {
1620b57cec5SDimitry Andric     switch (Imm & NVPTX::PTXCmpMode::BASE_MASK) {
1630b57cec5SDimitry Andric     default:
1640b57cec5SDimitry Andric       return;
1650b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::EQ:
1660b57cec5SDimitry Andric       O << ".eq";
1670b57cec5SDimitry Andric       break;
1680b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::NE:
1690b57cec5SDimitry Andric       O << ".ne";
1700b57cec5SDimitry Andric       break;
1710b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::LT:
1720b57cec5SDimitry Andric       O << ".lt";
1730b57cec5SDimitry Andric       break;
1740b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::LE:
1750b57cec5SDimitry Andric       O << ".le";
1760b57cec5SDimitry Andric       break;
1770b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::GT:
1780b57cec5SDimitry Andric       O << ".gt";
1790b57cec5SDimitry Andric       break;
1800b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::GE:
1810b57cec5SDimitry Andric       O << ".ge";
1820b57cec5SDimitry Andric       break;
1830b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::LO:
1840b57cec5SDimitry Andric       O << ".lo";
1850b57cec5SDimitry Andric       break;
1860b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::LS:
1870b57cec5SDimitry Andric       O << ".ls";
1880b57cec5SDimitry Andric       break;
1890b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::HI:
1900b57cec5SDimitry Andric       O << ".hi";
1910b57cec5SDimitry Andric       break;
1920b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::HS:
1930b57cec5SDimitry Andric       O << ".hs";
1940b57cec5SDimitry Andric       break;
1950b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::EQU:
1960b57cec5SDimitry Andric       O << ".equ";
1970b57cec5SDimitry Andric       break;
1980b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::NEU:
1990b57cec5SDimitry Andric       O << ".neu";
2000b57cec5SDimitry Andric       break;
2010b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::LTU:
2020b57cec5SDimitry Andric       O << ".ltu";
2030b57cec5SDimitry Andric       break;
2040b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::LEU:
2050b57cec5SDimitry Andric       O << ".leu";
2060b57cec5SDimitry Andric       break;
2070b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::GTU:
2080b57cec5SDimitry Andric       O << ".gtu";
2090b57cec5SDimitry Andric       break;
2100b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::GEU:
2110b57cec5SDimitry Andric       O << ".geu";
2120b57cec5SDimitry Andric       break;
2130b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::NUM:
2140b57cec5SDimitry Andric       O << ".num";
2150b57cec5SDimitry Andric       break;
2160b57cec5SDimitry Andric     case NVPTX::PTXCmpMode::NotANumber:
2170b57cec5SDimitry Andric       O << ".nan";
2180b57cec5SDimitry Andric       break;
2190b57cec5SDimitry Andric     }
2200b57cec5SDimitry Andric   } else {
2210b57cec5SDimitry Andric     llvm_unreachable("Empty Modifier");
2220b57cec5SDimitry Andric   }
2230b57cec5SDimitry Andric }
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric void NVPTXInstPrinter::printLdStCode(const MCInst *MI, int OpNum,
2260b57cec5SDimitry Andric                                      raw_ostream &O, const char *Modifier) {
2270b57cec5SDimitry Andric   if (Modifier) {
2280b57cec5SDimitry Andric     const MCOperand &MO = MI->getOperand(OpNum);
2290b57cec5SDimitry Andric     int Imm = (int) MO.getImm();
2300b57cec5SDimitry Andric     if (!strcmp(Modifier, "volatile")) {
2310b57cec5SDimitry Andric       if (Imm)
2320b57cec5SDimitry Andric         O << ".volatile";
2330b57cec5SDimitry Andric     } else if (!strcmp(Modifier, "addsp")) {
2340b57cec5SDimitry Andric       switch (Imm) {
2350b57cec5SDimitry Andric       case NVPTX::PTXLdStInstCode::GLOBAL:
2360b57cec5SDimitry Andric         O << ".global";
2370b57cec5SDimitry Andric         break;
2380b57cec5SDimitry Andric       case NVPTX::PTXLdStInstCode::SHARED:
2390b57cec5SDimitry Andric         O << ".shared";
2400b57cec5SDimitry Andric         break;
2410b57cec5SDimitry Andric       case NVPTX::PTXLdStInstCode::LOCAL:
2420b57cec5SDimitry Andric         O << ".local";
2430b57cec5SDimitry Andric         break;
2440b57cec5SDimitry Andric       case NVPTX::PTXLdStInstCode::PARAM:
2450b57cec5SDimitry Andric         O << ".param";
2460b57cec5SDimitry Andric         break;
2470b57cec5SDimitry Andric       case NVPTX::PTXLdStInstCode::CONSTANT:
2480b57cec5SDimitry Andric         O << ".const";
2490b57cec5SDimitry Andric         break;
2500b57cec5SDimitry Andric       case NVPTX::PTXLdStInstCode::GENERIC:
2510b57cec5SDimitry Andric         break;
2520b57cec5SDimitry Andric       default:
2530b57cec5SDimitry Andric         llvm_unreachable("Wrong Address Space");
2540b57cec5SDimitry Andric       }
2550b57cec5SDimitry Andric     } else if (!strcmp(Modifier, "sign")) {
2560b57cec5SDimitry Andric       if (Imm == NVPTX::PTXLdStInstCode::Signed)
2570b57cec5SDimitry Andric         O << "s";
2580b57cec5SDimitry Andric       else if (Imm == NVPTX::PTXLdStInstCode::Unsigned)
2590b57cec5SDimitry Andric         O << "u";
2600b57cec5SDimitry Andric       else if (Imm == NVPTX::PTXLdStInstCode::Untyped)
2610b57cec5SDimitry Andric         O << "b";
2620b57cec5SDimitry Andric       else if (Imm == NVPTX::PTXLdStInstCode::Float)
2630b57cec5SDimitry Andric         O << "f";
2640b57cec5SDimitry Andric       else
2650b57cec5SDimitry Andric         llvm_unreachable("Unknown register type");
2660b57cec5SDimitry Andric     } else if (!strcmp(Modifier, "vec")) {
2670b57cec5SDimitry Andric       if (Imm == NVPTX::PTXLdStInstCode::V2)
2680b57cec5SDimitry Andric         O << ".v2";
2690b57cec5SDimitry Andric       else if (Imm == NVPTX::PTXLdStInstCode::V4)
2700b57cec5SDimitry Andric         O << ".v4";
2710b57cec5SDimitry Andric     } else
2720b57cec5SDimitry Andric       llvm_unreachable("Unknown Modifier");
2730b57cec5SDimitry Andric   } else
2740b57cec5SDimitry Andric     llvm_unreachable("Empty Modifier");
2750b57cec5SDimitry Andric }
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric void NVPTXInstPrinter::printMmaCode(const MCInst *MI, int OpNum, raw_ostream &O,
2780b57cec5SDimitry Andric                                     const char *Modifier) {
2790b57cec5SDimitry Andric   const MCOperand &MO = MI->getOperand(OpNum);
2800b57cec5SDimitry Andric   int Imm = (int)MO.getImm();
2810b57cec5SDimitry Andric   if (Modifier == nullptr || strcmp(Modifier, "version") == 0) {
2820b57cec5SDimitry Andric     O << Imm; // Just print out PTX version
2830b57cec5SDimitry Andric   } else if (strcmp(Modifier, "aligned") == 0) {
2840b57cec5SDimitry Andric     // PTX63 requires '.aligned' in the name of the instruction.
2850b57cec5SDimitry Andric     if (Imm >= 63)
2860b57cec5SDimitry Andric       O << ".aligned";
2870b57cec5SDimitry Andric   } else
2880b57cec5SDimitry Andric     llvm_unreachable("Unknown Modifier");
2890b57cec5SDimitry Andric }
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric void NVPTXInstPrinter::printMemOperand(const MCInst *MI, int OpNum,
2920b57cec5SDimitry Andric                                        raw_ostream &O, const char *Modifier) {
2930b57cec5SDimitry Andric   printOperand(MI, OpNum, O);
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric   if (Modifier && !strcmp(Modifier, "add")) {
2960b57cec5SDimitry Andric     O << ", ";
2970b57cec5SDimitry Andric     printOperand(MI, OpNum + 1, O);
2980b57cec5SDimitry Andric   } else {
2990b57cec5SDimitry Andric     if (MI->getOperand(OpNum + 1).isImm() &&
3000b57cec5SDimitry Andric         MI->getOperand(OpNum + 1).getImm() == 0)
3010b57cec5SDimitry Andric       return; // don't print ',0' or '+0'
3020b57cec5SDimitry Andric     O << "+";
3030b57cec5SDimitry Andric     printOperand(MI, OpNum + 1, O);
3040b57cec5SDimitry Andric   }
3050b57cec5SDimitry Andric }
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric void NVPTXInstPrinter::printProtoIdent(const MCInst *MI, int OpNum,
3080b57cec5SDimitry Andric                                        raw_ostream &O, const char *Modifier) {
3090b57cec5SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNum);
3100b57cec5SDimitry Andric   assert(Op.isExpr() && "Call prototype is not an MCExpr?");
3110b57cec5SDimitry Andric   const MCExpr *Expr = Op.getExpr();
3120b57cec5SDimitry Andric   const MCSymbol &Sym = cast<MCSymbolRefExpr>(Expr)->getSymbol();
3130b57cec5SDimitry Andric   O << Sym.getName();
3140b57cec5SDimitry Andric }
3155f757f3fSDimitry Andric 
3165f757f3fSDimitry Andric void NVPTXInstPrinter::printPrmtMode(const MCInst *MI, int OpNum,
3175f757f3fSDimitry Andric                                      raw_ostream &O, const char *Modifier) {
3185f757f3fSDimitry Andric   const MCOperand &MO = MI->getOperand(OpNum);
3195f757f3fSDimitry Andric   int64_t Imm = MO.getImm();
3205f757f3fSDimitry Andric 
3215f757f3fSDimitry Andric   switch (Imm) {
3225f757f3fSDimitry Andric   default:
3235f757f3fSDimitry Andric     return;
3245f757f3fSDimitry Andric   case NVPTX::PTXPrmtMode::NONE:
3255f757f3fSDimitry Andric     break;
3265f757f3fSDimitry Andric   case NVPTX::PTXPrmtMode::F4E:
3275f757f3fSDimitry Andric     O << ".f4e";
3285f757f3fSDimitry Andric     break;
3295f757f3fSDimitry Andric   case NVPTX::PTXPrmtMode::B4E:
3305f757f3fSDimitry Andric     O << ".b4e";
3315f757f3fSDimitry Andric     break;
3325f757f3fSDimitry Andric   case NVPTX::PTXPrmtMode::RC8:
3335f757f3fSDimitry Andric     O << ".rc8";
3345f757f3fSDimitry Andric     break;
3355f757f3fSDimitry Andric   case NVPTX::PTXPrmtMode::ECL:
3365f757f3fSDimitry Andric     O << ".ecl";
3375f757f3fSDimitry Andric     break;
3385f757f3fSDimitry Andric   case NVPTX::PTXPrmtMode::ECR:
3395f757f3fSDimitry Andric     O << ".ecr";
3405f757f3fSDimitry Andric     break;
3415f757f3fSDimitry Andric   case NVPTX::PTXPrmtMode::RC16:
3425f757f3fSDimitry Andric     O << ".rc16";
3435f757f3fSDimitry Andric     break;
3445f757f3fSDimitry Andric   }
3455f757f3fSDimitry Andric }
346