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