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