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