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, MCRegister Reg) const { 35 // Decode the virtual register 36 // Must be kept in sync with NVPTXAsmPrinter::encodeVirtualRegister 37 unsigned RCId = (Reg.id() >> 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(Reg); 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 << "%rq"; 65 break; 66 } 67 68 unsigned VReg = Reg.id() & 0x0FFFFFFF; 69 OS << VReg; 70 } 71 72 void NVPTXInstPrinter::printInst(const MCInst *MI, uint64_t Address, 73 StringRef Annot, const MCSubtargetInfo &STI, 74 raw_ostream &OS) { 75 printInstruction(MI, Address, OS); 76 77 // Next always print the annotation. 78 printAnnotation(OS, Annot); 79 } 80 81 void NVPTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 82 raw_ostream &O) { 83 const MCOperand &Op = MI->getOperand(OpNo); 84 if (Op.isReg()) { 85 unsigned Reg = Op.getReg(); 86 printRegName(O, Reg); 87 } else if (Op.isImm()) { 88 markup(O, Markup::Immediate) << formatImm(Op.getImm()); 89 } else { 90 assert(Op.isExpr() && "Unknown operand kind in printOperand"); 91 Op.getExpr()->print(O, &MAI); 92 } 93 } 94 95 void NVPTXInstPrinter::printCvtMode(const MCInst *MI, int OpNum, raw_ostream &O, 96 const char *Modifier) { 97 const MCOperand &MO = MI->getOperand(OpNum); 98 int64_t Imm = MO.getImm(); 99 100 if (strcmp(Modifier, "ftz") == 0) { 101 // FTZ flag 102 if (Imm & NVPTX::PTXCvtMode::FTZ_FLAG) 103 O << ".ftz"; 104 } else if (strcmp(Modifier, "sat") == 0) { 105 // SAT flag 106 if (Imm & NVPTX::PTXCvtMode::SAT_FLAG) 107 O << ".sat"; 108 } else if (strcmp(Modifier, "relu") == 0) { 109 // RELU flag 110 if (Imm & NVPTX::PTXCvtMode::RELU_FLAG) 111 O << ".relu"; 112 } else if (strcmp(Modifier, "base") == 0) { 113 // Default operand 114 switch (Imm & NVPTX::PTXCvtMode::BASE_MASK) { 115 default: 116 return; 117 case NVPTX::PTXCvtMode::NONE: 118 break; 119 case NVPTX::PTXCvtMode::RNI: 120 O << ".rni"; 121 break; 122 case NVPTX::PTXCvtMode::RZI: 123 O << ".rzi"; 124 break; 125 case NVPTX::PTXCvtMode::RMI: 126 O << ".rmi"; 127 break; 128 case NVPTX::PTXCvtMode::RPI: 129 O << ".rpi"; 130 break; 131 case NVPTX::PTXCvtMode::RN: 132 O << ".rn"; 133 break; 134 case NVPTX::PTXCvtMode::RZ: 135 O << ".rz"; 136 break; 137 case NVPTX::PTXCvtMode::RM: 138 O << ".rm"; 139 break; 140 case NVPTX::PTXCvtMode::RP: 141 O << ".rp"; 142 break; 143 case NVPTX::PTXCvtMode::RNA: 144 O << ".rna"; 145 break; 146 } 147 } else { 148 llvm_unreachable("Invalid conversion modifier"); 149 } 150 } 151 152 void NVPTXInstPrinter::printCmpMode(const MCInst *MI, int OpNum, raw_ostream &O, 153 const char *Modifier) { 154 const MCOperand &MO = MI->getOperand(OpNum); 155 int64_t Imm = MO.getImm(); 156 157 if (strcmp(Modifier, "ftz") == 0) { 158 // FTZ flag 159 if (Imm & NVPTX::PTXCmpMode::FTZ_FLAG) 160 O << ".ftz"; 161 } else if (strcmp(Modifier, "base") == 0) { 162 switch (Imm & NVPTX::PTXCmpMode::BASE_MASK) { 163 default: 164 return; 165 case NVPTX::PTXCmpMode::EQ: 166 O << ".eq"; 167 break; 168 case NVPTX::PTXCmpMode::NE: 169 O << ".ne"; 170 break; 171 case NVPTX::PTXCmpMode::LT: 172 O << ".lt"; 173 break; 174 case NVPTX::PTXCmpMode::LE: 175 O << ".le"; 176 break; 177 case NVPTX::PTXCmpMode::GT: 178 O << ".gt"; 179 break; 180 case NVPTX::PTXCmpMode::GE: 181 O << ".ge"; 182 break; 183 case NVPTX::PTXCmpMode::LO: 184 O << ".lo"; 185 break; 186 case NVPTX::PTXCmpMode::LS: 187 O << ".ls"; 188 break; 189 case NVPTX::PTXCmpMode::HI: 190 O << ".hi"; 191 break; 192 case NVPTX::PTXCmpMode::HS: 193 O << ".hs"; 194 break; 195 case NVPTX::PTXCmpMode::EQU: 196 O << ".equ"; 197 break; 198 case NVPTX::PTXCmpMode::NEU: 199 O << ".neu"; 200 break; 201 case NVPTX::PTXCmpMode::LTU: 202 O << ".ltu"; 203 break; 204 case NVPTX::PTXCmpMode::LEU: 205 O << ".leu"; 206 break; 207 case NVPTX::PTXCmpMode::GTU: 208 O << ".gtu"; 209 break; 210 case NVPTX::PTXCmpMode::GEU: 211 O << ".geu"; 212 break; 213 case NVPTX::PTXCmpMode::NUM: 214 O << ".num"; 215 break; 216 case NVPTX::PTXCmpMode::NotANumber: 217 O << ".nan"; 218 break; 219 } 220 } else { 221 llvm_unreachable("Empty Modifier"); 222 } 223 } 224 225 void NVPTXInstPrinter::printLdStCode(const MCInst *MI, int OpNum, 226 raw_ostream &O, const char *Modifier) { 227 if (Modifier) { 228 const MCOperand &MO = MI->getOperand(OpNum); 229 int Imm = (int) MO.getImm(); 230 if (!strcmp(Modifier, "volatile")) { 231 if (Imm) 232 O << ".volatile"; 233 } else if (!strcmp(Modifier, "addsp")) { 234 switch (Imm) { 235 case NVPTX::PTXLdStInstCode::GLOBAL: 236 O << ".global"; 237 break; 238 case NVPTX::PTXLdStInstCode::SHARED: 239 O << ".shared"; 240 break; 241 case NVPTX::PTXLdStInstCode::LOCAL: 242 O << ".local"; 243 break; 244 case NVPTX::PTXLdStInstCode::PARAM: 245 O << ".param"; 246 break; 247 case NVPTX::PTXLdStInstCode::CONSTANT: 248 O << ".const"; 249 break; 250 case NVPTX::PTXLdStInstCode::GENERIC: 251 break; 252 default: 253 llvm_unreachable("Wrong Address Space"); 254 } 255 } else if (!strcmp(Modifier, "sign")) { 256 if (Imm == NVPTX::PTXLdStInstCode::Signed) 257 O << "s"; 258 else if (Imm == NVPTX::PTXLdStInstCode::Unsigned) 259 O << "u"; 260 else if (Imm == NVPTX::PTXLdStInstCode::Untyped) 261 O << "b"; 262 else if (Imm == NVPTX::PTXLdStInstCode::Float) 263 O << "f"; 264 else 265 llvm_unreachable("Unknown register type"); 266 } else if (!strcmp(Modifier, "vec")) { 267 if (Imm == NVPTX::PTXLdStInstCode::V2) 268 O << ".v2"; 269 else if (Imm == NVPTX::PTXLdStInstCode::V4) 270 O << ".v4"; 271 } else 272 llvm_unreachable("Unknown Modifier"); 273 } else 274 llvm_unreachable("Empty Modifier"); 275 } 276 277 void NVPTXInstPrinter::printMmaCode(const MCInst *MI, int OpNum, raw_ostream &O, 278 const char *Modifier) { 279 const MCOperand &MO = MI->getOperand(OpNum); 280 int Imm = (int)MO.getImm(); 281 if (Modifier == nullptr || strcmp(Modifier, "version") == 0) { 282 O << Imm; // Just print out PTX version 283 } else if (strcmp(Modifier, "aligned") == 0) { 284 // PTX63 requires '.aligned' in the name of the instruction. 285 if (Imm >= 63) 286 O << ".aligned"; 287 } else 288 llvm_unreachable("Unknown Modifier"); 289 } 290 291 void NVPTXInstPrinter::printMemOperand(const MCInst *MI, int OpNum, 292 raw_ostream &O, const char *Modifier) { 293 printOperand(MI, OpNum, O); 294 295 if (Modifier && !strcmp(Modifier, "add")) { 296 O << ", "; 297 printOperand(MI, OpNum + 1, O); 298 } else { 299 if (MI->getOperand(OpNum + 1).isImm() && 300 MI->getOperand(OpNum + 1).getImm() == 0) 301 return; // don't print ',0' or '+0' 302 O << "+"; 303 printOperand(MI, OpNum + 1, O); 304 } 305 } 306 307 void NVPTXInstPrinter::printProtoIdent(const MCInst *MI, int OpNum, 308 raw_ostream &O, const char *Modifier) { 309 const MCOperand &Op = MI->getOperand(OpNum); 310 assert(Op.isExpr() && "Call prototype is not an MCExpr?"); 311 const MCExpr *Expr = Op.getExpr(); 312 const MCSymbol &Sym = cast<MCSymbolRefExpr>(Expr)->getSymbol(); 313 O << Sym.getName(); 314 } 315 316 void NVPTXInstPrinter::printPrmtMode(const MCInst *MI, int OpNum, 317 raw_ostream &O, const char *Modifier) { 318 const MCOperand &MO = MI->getOperand(OpNum); 319 int64_t Imm = MO.getImm(); 320 321 switch (Imm) { 322 default: 323 return; 324 case NVPTX::PTXPrmtMode::NONE: 325 break; 326 case NVPTX::PTXPrmtMode::F4E: 327 O << ".f4e"; 328 break; 329 case NVPTX::PTXPrmtMode::B4E: 330 O << ".b4e"; 331 break; 332 case NVPTX::PTXPrmtMode::RC8: 333 O << ".rc8"; 334 break; 335 case NVPTX::PTXPrmtMode::ECL: 336 O << ".ecl"; 337 break; 338 case NVPTX::PTXPrmtMode::ECR: 339 O << ".ecr"; 340 break; 341 case NVPTX::PTXPrmtMode::RC16: 342 O << ".rc16"; 343 break; 344 } 345 } 346