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