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 #define DEBUG_TYPE "asm-printer" 15 #include "InstPrinter/NVPTXInstPrinter.h" 16 #include "NVPTX.h" 17 #include "MCTargetDesc/NVPTXBaseInfo.h" 18 #include "llvm/MC/MCExpr.h" 19 #include "llvm/MC/MCInst.h" 20 #include "llvm/MC/MCInstrInfo.h" 21 #include "llvm/MC/MCSubtargetInfo.h" 22 #include "llvm/Support/ErrorHandling.h" 23 #include "llvm/Support/FormattedStream.h" 24 #include <cctype> 25 using namespace llvm; 26 27 #include "NVPTXGenAsmWriter.inc" 28 29 30 NVPTXInstPrinter::NVPTXInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, 31 const MCRegisterInfo &MRI, 32 const MCSubtargetInfo &STI) 33 : MCInstPrinter(MAI, MII, MRI) { 34 setAvailableFeatures(STI.getFeatureBits()); 35 } 36 37 void NVPTXInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { 38 // Decode the virtual register 39 // Must be kept in sync with NVPTXAsmPrinter::encodeVirtualRegister 40 unsigned RCId = (RegNo >> 28); 41 switch (RCId) { 42 default: report_fatal_error("Bad virtual register encoding"); 43 case 0: 44 // This is actually a physical register, so defer to the autogenerated 45 // register printer 46 OS << getRegisterName(RegNo); 47 return; 48 case 1: 49 OS << "%p"; 50 break; 51 case 2: 52 OS << "%rs"; 53 break; 54 case 3: 55 OS << "%r"; 56 break; 57 case 4: 58 OS << "%rl"; 59 break; 60 case 5: 61 OS << "%f"; 62 break; 63 case 6: 64 OS << "%fl"; 65 break; 66 } 67 68 unsigned VReg = RegNo & 0x0FFFFFFF; 69 OS << VReg; 70 } 71 72 void NVPTXInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, 73 StringRef Annot) { 74 printInstruction(MI, OS); 75 76 // Next always print the annotation. 77 printAnnotation(OS, Annot); 78 } 79 80 void NVPTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 81 raw_ostream &O) { 82 const MCOperand &Op = MI->getOperand(OpNo); 83 if (Op.isReg()) { 84 unsigned Reg = Op.getReg(); 85 printRegName(O, Reg); 86 } else if (Op.isImm()) { 87 O << markup("<imm:") << formatImm(Op.getImm()) << markup(">"); 88 } else { 89 assert(Op.isExpr() && "Unknown operand kind in printOperand"); 90 O << *Op.getExpr(); 91 } 92 } 93 94 void NVPTXInstPrinter::printCvtMode(const MCInst *MI, int OpNum, raw_ostream &O, 95 const char *Modifier) { 96 const MCOperand &MO = MI->getOperand(OpNum); 97 int64_t Imm = MO.getImm(); 98 99 if (strcmp(Modifier, "ftz") == 0) { 100 // FTZ flag 101 if (Imm & NVPTX::PTXCvtMode::FTZ_FLAG) 102 O << ".ftz"; 103 } else if (strcmp(Modifier, "sat") == 0) { 104 // SAT flag 105 if (Imm & NVPTX::PTXCvtMode::SAT_FLAG) 106 O << ".sat"; 107 } else if (strcmp(Modifier, "base") == 0) { 108 // Default operand 109 switch (Imm & NVPTX::PTXCvtMode::BASE_MASK) { 110 default: 111 return; 112 case NVPTX::PTXCvtMode::NONE: 113 break; 114 case NVPTX::PTXCvtMode::RNI: 115 O << ".rni"; 116 break; 117 case NVPTX::PTXCvtMode::RZI: 118 O << ".rzi"; 119 break; 120 case NVPTX::PTXCvtMode::RMI: 121 O << ".rmi"; 122 break; 123 case NVPTX::PTXCvtMode::RPI: 124 O << ".rpi"; 125 break; 126 case NVPTX::PTXCvtMode::RN: 127 O << ".rn"; 128 break; 129 case NVPTX::PTXCvtMode::RZ: 130 O << ".rz"; 131 break; 132 case NVPTX::PTXCvtMode::RM: 133 O << ".rm"; 134 break; 135 case NVPTX::PTXCvtMode::RP: 136 O << ".rp"; 137 break; 138 } 139 } else { 140 llvm_unreachable("Invalid conversion modifier"); 141 } 142 } 143 144 void NVPTXInstPrinter::printCmpMode(const MCInst *MI, int OpNum, raw_ostream &O, 145 const char *Modifier) { 146 const MCOperand &MO = MI->getOperand(OpNum); 147 int64_t Imm = MO.getImm(); 148 149 if (strcmp(Modifier, "ftz") == 0) { 150 // FTZ flag 151 if (Imm & NVPTX::PTXCmpMode::FTZ_FLAG) 152 O << ".ftz"; 153 } else if (strcmp(Modifier, "base") == 0) { 154 switch (Imm & NVPTX::PTXCmpMode::BASE_MASK) { 155 default: 156 return; 157 case NVPTX::PTXCmpMode::EQ: 158 O << ".eq"; 159 break; 160 case NVPTX::PTXCmpMode::NE: 161 O << ".ne"; 162 break; 163 case NVPTX::PTXCmpMode::LT: 164 O << ".lt"; 165 break; 166 case NVPTX::PTXCmpMode::LE: 167 O << ".le"; 168 break; 169 case NVPTX::PTXCmpMode::GT: 170 O << ".gt"; 171 break; 172 case NVPTX::PTXCmpMode::GE: 173 O << ".ge"; 174 break; 175 case NVPTX::PTXCmpMode::LO: 176 O << ".lo"; 177 break; 178 case NVPTX::PTXCmpMode::LS: 179 O << ".ls"; 180 break; 181 case NVPTX::PTXCmpMode::HI: 182 O << ".hi"; 183 break; 184 case NVPTX::PTXCmpMode::HS: 185 O << ".hs"; 186 break; 187 case NVPTX::PTXCmpMode::EQU: 188 O << ".equ"; 189 break; 190 case NVPTX::PTXCmpMode::NEU: 191 O << ".neu"; 192 break; 193 case NVPTX::PTXCmpMode::LTU: 194 O << ".ltu"; 195 break; 196 case NVPTX::PTXCmpMode::LEU: 197 O << ".leu"; 198 break; 199 case NVPTX::PTXCmpMode::GTU: 200 O << ".gtu"; 201 break; 202 case NVPTX::PTXCmpMode::GEU: 203 O << ".geu"; 204 break; 205 case NVPTX::PTXCmpMode::NUM: 206 O << ".num"; 207 break; 208 case NVPTX::PTXCmpMode::NotANumber: 209 O << ".nan"; 210 break; 211 } 212 } else { 213 llvm_unreachable("Empty Modifier"); 214 } 215 } 216 217 void NVPTXInstPrinter::printLdStCode(const MCInst *MI, int OpNum, 218 raw_ostream &O, const char *Modifier) { 219 if (Modifier) { 220 const MCOperand &MO = MI->getOperand(OpNum); 221 int Imm = (int) MO.getImm(); 222 if (!strcmp(Modifier, "volatile")) { 223 if (Imm) 224 O << ".volatile"; 225 } else if (!strcmp(Modifier, "addsp")) { 226 switch (Imm) { 227 case NVPTX::PTXLdStInstCode::GLOBAL: 228 O << ".global"; 229 break; 230 case NVPTX::PTXLdStInstCode::SHARED: 231 O << ".shared"; 232 break; 233 case NVPTX::PTXLdStInstCode::LOCAL: 234 O << ".local"; 235 break; 236 case NVPTX::PTXLdStInstCode::PARAM: 237 O << ".param"; 238 break; 239 case NVPTX::PTXLdStInstCode::CONSTANT: 240 O << ".const"; 241 break; 242 case NVPTX::PTXLdStInstCode::GENERIC: 243 break; 244 default: 245 llvm_unreachable("Wrong Address Space"); 246 } 247 } else if (!strcmp(Modifier, "sign")) { 248 if (Imm == NVPTX::PTXLdStInstCode::Signed) 249 O << "s"; 250 else if (Imm == NVPTX::PTXLdStInstCode::Unsigned) 251 O << "u"; 252 else 253 O << "f"; 254 } else if (!strcmp(Modifier, "vec")) { 255 if (Imm == NVPTX::PTXLdStInstCode::V2) 256 O << ".v2"; 257 else if (Imm == NVPTX::PTXLdStInstCode::V4) 258 O << ".v4"; 259 } else 260 llvm_unreachable("Unknown Modifier"); 261 } else 262 llvm_unreachable("Empty Modifier"); 263 } 264 265 void NVPTXInstPrinter::printMemOperand(const MCInst *MI, int OpNum, 266 raw_ostream &O, const char *Modifier) { 267 printOperand(MI, OpNum, O); 268 269 if (Modifier && !strcmp(Modifier, "add")) { 270 O << ", "; 271 printOperand(MI, OpNum + 1, O); 272 } else { 273 if (MI->getOperand(OpNum + 1).isImm() && 274 MI->getOperand(OpNum + 1).getImm() == 0) 275 return; // don't print ',0' or '+0' 276 O << "+"; 277 printOperand(MI, OpNum + 1, O); 278 } 279 } 280