Home | History | Annotate | Download | only in InstPrinter
      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 
     32 NVPTXInstPrinter::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 
     39 void 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 
     74 void 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 
     82 void 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 
     96 void 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 
    146 void 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 
    219 void 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 
    267 void 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 
    283 void 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