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