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, "base") == 0) { 112 // Default operand 113 switch (Imm & NVPTX::PTXCvtMode::BASE_MASK) { 114 default: 115 return; 116 case NVPTX::PTXCvtMode::NONE: 117 break; 118 case NVPTX::PTXCvtMode::RNI: 119 O << ".rni"; 120 break; 121 case NVPTX::PTXCvtMode::RZI: 122 O << ".rzi"; 123 break; 124 case NVPTX::PTXCvtMode::RMI: 125 O << ".rmi"; 126 break; 127 case NVPTX::PTXCvtMode::RPI: 128 O << ".rpi"; 129 break; 130 case NVPTX::PTXCvtMode::RN: 131 O << ".rn"; 132 break; 133 case NVPTX::PTXCvtMode::RZ: 134 O << ".rz"; 135 break; 136 case NVPTX::PTXCvtMode::RM: 137 O << ".rm"; 138 break; 139 case NVPTX::PTXCvtMode::RP: 140 O << ".rp"; 141 break; 142 } 143 } else { 144 llvm_unreachable("Invalid conversion modifier"); 145 } 146 } 147 148 void NVPTXInstPrinter::printCmpMode(const MCInst *MI, int OpNum, raw_ostream &O, 149 const char *Modifier) { 150 const MCOperand &MO = MI->getOperand(OpNum); 151 int64_t Imm = MO.getImm(); 152 153 if (strcmp(Modifier, "ftz") == 0) { 154 // FTZ flag 155 if (Imm & NVPTX::PTXCmpMode::FTZ_FLAG) 156 O << ".ftz"; 157 } else if (strcmp(Modifier, "base") == 0) { 158 switch (Imm & NVPTX::PTXCmpMode::BASE_MASK) { 159 default: 160 return; 161 case NVPTX::PTXCmpMode::EQ: 162 O << ".eq"; 163 break; 164 case NVPTX::PTXCmpMode::NE: 165 O << ".ne"; 166 break; 167 case NVPTX::PTXCmpMode::LT: 168 O << ".lt"; 169 break; 170 case NVPTX::PTXCmpMode::LE: 171 O << ".le"; 172 break; 173 case NVPTX::PTXCmpMode::GT: 174 O << ".gt"; 175 break; 176 case NVPTX::PTXCmpMode::GE: 177 O << ".ge"; 178 break; 179 case NVPTX::PTXCmpMode::LO: 180 O << ".lo"; 181 break; 182 case NVPTX::PTXCmpMode::LS: 183 O << ".ls"; 184 break; 185 case NVPTX::PTXCmpMode::HI: 186 O << ".hi"; 187 break; 188 case NVPTX::PTXCmpMode::HS: 189 O << ".hs"; 190 break; 191 case NVPTX::PTXCmpMode::EQU: 192 O << ".equ"; 193 break; 194 case NVPTX::PTXCmpMode::NEU: 195 O << ".neu"; 196 break; 197 case NVPTX::PTXCmpMode::LTU: 198 O << ".ltu"; 199 break; 200 case NVPTX::PTXCmpMode::LEU: 201 O << ".leu"; 202 break; 203 case NVPTX::PTXCmpMode::GTU: 204 O << ".gtu"; 205 break; 206 case NVPTX::PTXCmpMode::GEU: 207 O << ".geu"; 208 break; 209 case NVPTX::PTXCmpMode::NUM: 210 O << ".num"; 211 break; 212 case NVPTX::PTXCmpMode::NotANumber: 213 O << ".nan"; 214 break; 215 } 216 } else { 217 llvm_unreachable("Empty Modifier"); 218 } 219 } 220 221 void NVPTXInstPrinter::printLdStCode(const MCInst *MI, int OpNum, 222 raw_ostream &O, const char *Modifier) { 223 if (Modifier) { 224 const MCOperand &MO = MI->getOperand(OpNum); 225 int Imm = (int) MO.getImm(); 226 if (!strcmp(Modifier, "volatile")) { 227 if (Imm) 228 O << ".volatile"; 229 } else if (!strcmp(Modifier, "addsp")) { 230 switch (Imm) { 231 case NVPTX::PTXLdStInstCode::GLOBAL: 232 O << ".global"; 233 break; 234 case NVPTX::PTXLdStInstCode::SHARED: 235 O << ".shared"; 236 break; 237 case NVPTX::PTXLdStInstCode::LOCAL: 238 O << ".local"; 239 break; 240 case NVPTX::PTXLdStInstCode::PARAM: 241 O << ".param"; 242 break; 243 case NVPTX::PTXLdStInstCode::CONSTANT: 244 O << ".const"; 245 break; 246 case NVPTX::PTXLdStInstCode::GENERIC: 247 break; 248 default: 249 llvm_unreachable("Wrong Address Space"); 250 } 251 } else if (!strcmp(Modifier, "sign")) { 252 if (Imm == NVPTX::PTXLdStInstCode::Signed) 253 O << "s"; 254 else if (Imm == NVPTX::PTXLdStInstCode::Unsigned) 255 O << "u"; 256 else if (Imm == NVPTX::PTXLdStInstCode::Untyped) 257 O << "b"; 258 else if (Imm == NVPTX::PTXLdStInstCode::Float) 259 O << "f"; 260 else 261 llvm_unreachable("Unknown register type"); 262 } else if (!strcmp(Modifier, "vec")) { 263 if (Imm == NVPTX::PTXLdStInstCode::V2) 264 O << ".v2"; 265 else if (Imm == NVPTX::PTXLdStInstCode::V4) 266 O << ".v4"; 267 } else 268 llvm_unreachable("Unknown Modifier"); 269 } else 270 llvm_unreachable("Empty Modifier"); 271 } 272 273 void NVPTXInstPrinter::printMmaCode(const MCInst *MI, int OpNum, raw_ostream &O, 274 const char *Modifier) { 275 const MCOperand &MO = MI->getOperand(OpNum); 276 int Imm = (int)MO.getImm(); 277 if (Modifier == nullptr || strcmp(Modifier, "version") == 0) { 278 O << Imm; // Just print out PTX version 279 } else if (strcmp(Modifier, "aligned") == 0) { 280 // PTX63 requires '.aligned' in the name of the instruction. 281 if (Imm >= 63) 282 O << ".aligned"; 283 } else 284 llvm_unreachable("Unknown Modifier"); 285 } 286 287 void NVPTXInstPrinter::printMemOperand(const MCInst *MI, int OpNum, 288 raw_ostream &O, const char *Modifier) { 289 printOperand(MI, OpNum, O); 290 291 if (Modifier && !strcmp(Modifier, "add")) { 292 O << ", "; 293 printOperand(MI, OpNum + 1, O); 294 } else { 295 if (MI->getOperand(OpNum + 1).isImm() && 296 MI->getOperand(OpNum + 1).getImm() == 0) 297 return; // don't print ',0' or '+0' 298 O << "+"; 299 printOperand(MI, OpNum + 1, O); 300 } 301 } 302 303 void NVPTXInstPrinter::printProtoIdent(const MCInst *MI, int OpNum, 304 raw_ostream &O, const char *Modifier) { 305 const MCOperand &Op = MI->getOperand(OpNum); 306 assert(Op.isExpr() && "Call prototype is not an MCExpr?"); 307 const MCExpr *Expr = Op.getExpr(); 308 const MCSymbol &Sym = cast<MCSymbolRefExpr>(Expr)->getSymbol(); 309 O << Sym.getName(); 310 } 311