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