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