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