1 //===-- NVPTXInstPrinter.cpp - PTX assembly instruction printing ----------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Print MCInst instructions to .ptx format. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "InstPrinter/NVPTXInstPrinter.h" 15 #include "MCTargetDesc/NVPTXBaseInfo.h" 16 #include "NVPTX.h" 17 #include "llvm/MC/MCExpr.h" 18 #include "llvm/MC/MCInst.h" 19 #include "llvm/MC/MCInstrInfo.h" 20 #include "llvm/MC/MCSubtargetInfo.h" 21 #include "llvm/MC/MCSymbol.h" 22 #include "llvm/Support/ErrorHandling.h" 23 #include "llvm/Support/FormattedStream.h" 24 #include <cctype> 25 using namespace llvm; 26 27 #define DEBUG_TYPE "asm-printer" 28 29 #include "NVPTXGenAsmWriter.inc" 30 31 NVPTXInstPrinter::NVPTXInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, 32 const MCRegisterInfo &MRI) 33 : MCInstPrinter(MAI, MII, MRI) {} 34 35 void NVPTXInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { 36 // Decode the virtual register 37 // Must be kept in sync with NVPTXAsmPrinter::encodeVirtualRegister 38 unsigned RCId = (RegNo >> 28); 39 switch (RCId) { 40 default: report_fatal_error("Bad virtual register encoding"); 41 case 0: 42 // This is actually a physical register, so defer to the autogenerated 43 // register printer 44 OS << getRegisterName(RegNo); 45 return; 46 case 1: 47 OS << "%p"; 48 break; 49 case 2: 50 OS << "%rs"; 51 break; 52 case 3: 53 OS << "%r"; 54 break; 55 case 4: 56 OS << "%rd"; 57 break; 58 case 5: 59 OS << "%f"; 60 break; 61 case 6: 62 OS << "%fd"; 63 break; 64 case 7: 65 OS << "%h"; 66 break; 67 case 8: 68 OS << "%hh"; 69 break; 70 } 71 72 unsigned VReg = RegNo & 0x0FFFFFFF; 73 OS << VReg; 74 } 75 76 void NVPTXInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, 77 StringRef Annot, const MCSubtargetInfo &STI) { 78 printInstruction(MI, 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::printMemOperand(const MCInst *MI, int OpNum, 274 raw_ostream &O, const char *Modifier) { 275 printOperand(MI, OpNum, O); 276 277 if (Modifier && !strcmp(Modifier, "add")) { 278 O << ", "; 279 printOperand(MI, OpNum + 1, O); 280 } else { 281 if (MI->getOperand(OpNum + 1).isImm() && 282 MI->getOperand(OpNum + 1).getImm() == 0) 283 return; // don't print ',0' or '+0' 284 O << "+"; 285 printOperand(MI, OpNum + 1, O); 286 } 287 } 288 289 void NVPTXInstPrinter::printProtoIdent(const MCInst *MI, int OpNum, 290 raw_ostream &O, const char *Modifier) { 291 const MCOperand &Op = MI->getOperand(OpNum); 292 assert(Op.isExpr() && "Call prototype is not an MCExpr?"); 293 const MCExpr *Expr = Op.getExpr(); 294 const MCSymbol &Sym = cast<MCSymbolRefExpr>(Expr)->getSymbol(); 295 O << Sym.getName(); 296 } 297