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 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