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