Home | History | Annotate | Download | only in InstPrinter
      1 //===-- LanaiInstPrinter.cpp - Convert Lanai MCInst to asm syntax ---------===//
      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 // This class prints an Lanai MCInst to a .s file.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "LanaiInstPrinter.h"
     15 #include "Lanai.h"
     16 #include "MCTargetDesc/LanaiMCExpr.h"
     17 #include "llvm/MC/MCAsmInfo.h"
     18 #include "llvm/MC/MCExpr.h"
     19 #include "llvm/MC/MCInst.h"
     20 #include "llvm/MC/MCSymbol.h"
     21 #include "llvm/Support/ErrorHandling.h"
     22 #include "llvm/Support/FormattedStream.h"
     23 
     24 using namespace llvm;
     25 
     26 #define DEBUG_TYPE "asm-printer"
     27 
     28 // Include the auto-generated portion of the assembly writer.
     29 #define PRINT_ALIAS_INSTR
     30 #include "LanaiGenAsmWriter.inc"
     31 
     32 void LanaiInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
     33   OS << StringRef(getRegisterName(RegNo)).lower();
     34 }
     35 
     36 bool LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
     37                                  StringRef Alias, unsigned OpNo0,
     38                                  unsigned OpNo1) {
     39   OS << "\t" << Alias << " ";
     40   printOperand(MI, OpNo0, OS);
     41   OS << ", ";
     42   printOperand(MI, OpNo1, OS);
     43   return true;
     44 }
     45 
     46 static bool usesGivenOffset(const MCInst *MI, int AddOffset) {
     47   unsigned AluCode = MI->getOperand(3).getImm();
     48   return LPAC::encodeLanaiAluCode(AluCode) == LPAC::ADD &&
     49          (MI->getOperand(2).getImm() == AddOffset ||
     50           MI->getOperand(2).getImm() == -AddOffset);
     51 }
     52 
     53 static bool isPreIncrementForm(const MCInst *MI, int AddOffset) {
     54   unsigned AluCode = MI->getOperand(3).getImm();
     55   return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset);
     56 }
     57 
     58 static bool isPostIncrementForm(const MCInst *MI, int AddOffset) {
     59   unsigned AluCode = MI->getOperand(3).getImm();
     60   return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset);
     61 }
     62 
     63 static StringRef decIncOperator(const MCInst *MI) {
     64   if (MI->getOperand(2).getImm() < 0)
     65     return "--";
     66   return "++";
     67 }
     68 
     69 bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI,
     70                                                 raw_ostream &OS,
     71                                                 StringRef Opcode,
     72                                                 int AddOffset) {
     73   if (isPreIncrementForm(MI, AddOffset)) {
     74     OS << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%"
     75        << getRegisterName(MI->getOperand(1).getReg()) << "], %"
     76        << getRegisterName(MI->getOperand(0).getReg());
     77     return true;
     78   }
     79   if (isPostIncrementForm(MI, AddOffset)) {
     80     OS << "\t" << Opcode << "\t[%"
     81        << getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI)
     82        << "], %" << getRegisterName(MI->getOperand(0).getReg());
     83     return true;
     84   }
     85   return false;
     86 }
     87 
     88 bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI,
     89                                                  raw_ostream &OS,
     90                                                  StringRef Opcode,
     91                                                  int AddOffset) {
     92   if (isPreIncrementForm(MI, AddOffset)) {
     93     OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
     94        << ", [" << decIncOperator(MI) << "%"
     95        << getRegisterName(MI->getOperand(1).getReg()) << "]";
     96     return true;
     97   }
     98   if (isPostIncrementForm(MI, AddOffset)) {
     99     OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
    100        << ", [%" << getRegisterName(MI->getOperand(1).getReg())
    101        << decIncOperator(MI) << "]";
    102     return true;
    103   }
    104   return false;
    105 }
    106 
    107 bool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &OS) {
    108   switch (MI->getOpcode()) {
    109   case Lanai::LDW_RI:
    110     // ld 4[*%rN], %rX => ld [++imm], %rX
    111     // ld -4[*%rN], %rX => ld [--imm], %rX
    112     // ld 4[%rN*], %rX => ld [imm++], %rX
    113     // ld -4[%rN*], %rX => ld [imm--], %rX
    114     return printMemoryLoadIncrement(MI, OS, "ld", 4);
    115   case Lanai::LDHs_RI:
    116     return printMemoryLoadIncrement(MI, OS, "ld.h", 2);
    117   case Lanai::LDHz_RI:
    118     return printMemoryLoadIncrement(MI, OS, "uld.h", 2);
    119   case Lanai::LDBs_RI:
    120     return printMemoryLoadIncrement(MI, OS, "ld.b", 1);
    121   case Lanai::LDBz_RI:
    122     return printMemoryLoadIncrement(MI, OS, "uld.b", 1);
    123   case Lanai::SW_RI:
    124     // st %rX, 4[*%rN] => st %rX, [++imm]
    125     // st %rX, -4[*%rN] => st %rX, [--imm]
    126     // st %rX, 4[%rN*] => st %rX, [imm++]
    127     // st %rX, -4[%rN*] => st %rX, [imm--]
    128     return printMemoryStoreIncrement(MI, OS, "st", 4);
    129   case Lanai::STH_RI:
    130     return printMemoryStoreIncrement(MI, OS, "st.h", 2);
    131   case Lanai::STB_RI:
    132     return printMemoryStoreIncrement(MI, OS, "st.b", 1);
    133   default:
    134     return false;
    135   }
    136 }
    137 
    138 void LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
    139                                  StringRef Annotation,
    140                                  const MCSubtargetInfo &STI) {
    141   if (!printAlias(MI, OS) && !printAliasInstr(MI, OS))
    142     printInstruction(MI, OS);
    143   printAnnotation(OS, Annotation);
    144 }
    145 
    146 void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
    147                                     raw_ostream &OS, const char *Modifier) {
    148   assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
    149   const MCOperand &Op = MI->getOperand(OpNo);
    150   if (Op.isReg())
    151     OS << "%" << getRegisterName(Op.getReg());
    152   else if (Op.isImm())
    153     OS << formatHex(Op.getImm());
    154   else {
    155     assert(Op.isExpr() && "Expected an expression");
    156     Op.getExpr()->print(OS, &MAI);
    157   }
    158 }
    159 
    160 void LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo,
    161                                           raw_ostream &OS) {
    162   const MCOperand &Op = MI->getOperand(OpNo);
    163   if (Op.isImm()) {
    164     OS << '[' << formatHex(Op.getImm()) << ']';
    165   } else {
    166     // Symbolic operand will be lowered to immediate value by linker
    167     assert(Op.isExpr() && "Expected an expression");
    168     OS << '[';
    169     Op.getExpr()->print(OS, &MAI);
    170     OS << ']';
    171   }
    172 }
    173 
    174 void LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo,
    175                                            raw_ostream &OS) {
    176   const MCOperand &Op = MI->getOperand(OpNo);
    177   if (Op.isImm()) {
    178     OS << formatHex(Op.getImm() << 16);
    179   } else {
    180     // Symbolic operand will be lowered to immediate value by linker
    181     assert(Op.isExpr() && "Expected an expression");
    182     Op.getExpr()->print(OS, &MAI);
    183   }
    184 }
    185 
    186 void LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo,
    187                                               raw_ostream &OS) {
    188   const MCOperand &Op = MI->getOperand(OpNo);
    189   if (Op.isImm()) {
    190     OS << formatHex((Op.getImm() << 16) | 0xffff);
    191   } else {
    192     // Symbolic operand will be lowered to immediate value by linker
    193     assert(Op.isExpr() && "Expected an expression");
    194     Op.getExpr()->print(OS, &MAI);
    195   }
    196 }
    197 
    198 void LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo,
    199                                               raw_ostream &OS) {
    200   const MCOperand &Op = MI->getOperand(OpNo);
    201   if (Op.isImm()) {
    202     OS << formatHex(0xffff0000 | Op.getImm());
    203   } else {
    204     // Symbolic operand will be lowered to immediate value by linker
    205     assert(Op.isExpr() && "Expected an expression");
    206     Op.getExpr()->print(OS, &MAI);
    207   }
    208 }
    209 
    210 static void printMemoryBaseRegister(raw_ostream &OS, const unsigned AluCode,
    211                                     const MCOperand &RegOp) {
    212   assert(RegOp.isReg() && "Register operand expected");
    213   OS << "[";
    214   if (LPAC::isPreOp(AluCode))
    215     OS << "*";
    216   OS << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg());
    217   if (LPAC::isPostOp(AluCode))
    218     OS << "*";
    219   OS << "]";
    220 }
    221 
    222 template <unsigned SizeInBits>
    223 static void printMemoryImmediateOffset(const MCAsmInfo &MAI,
    224                                        const MCOperand &OffsetOp,
    225                                        raw_ostream &OS) {
    226   assert((OffsetOp.isImm() || OffsetOp.isExpr()) && "Immediate expected");
    227   if (OffsetOp.isImm()) {
    228     assert(isInt<SizeInBits>(OffsetOp.getImm()) && "Constant value truncated");
    229     OS << OffsetOp.getImm();
    230   } else
    231     OffsetOp.getExpr()->print(OS, &MAI);
    232 }
    233 
    234 void LanaiInstPrinter::printMemRiOperand(const MCInst *MI, int OpNo,
    235                                          raw_ostream &OS,
    236                                          const char *Modifier) {
    237   const MCOperand &RegOp = MI->getOperand(OpNo);
    238   const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
    239   const MCOperand &AluOp = MI->getOperand(OpNo + 2);
    240   const unsigned AluCode = AluOp.getImm();
    241 
    242   // Offset
    243   printMemoryImmediateOffset<16>(MAI, OffsetOp, OS);
    244 
    245   // Register
    246   printMemoryBaseRegister(OS, AluCode, RegOp);
    247 }
    248 
    249 void LanaiInstPrinter::printMemRrOperand(const MCInst *MI, int OpNo,
    250                                          raw_ostream &OS,
    251                                          const char *Modifier) {
    252   const MCOperand &RegOp = MI->getOperand(OpNo);
    253   const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
    254   const MCOperand &AluOp = MI->getOperand(OpNo + 2);
    255   const unsigned AluCode = AluOp.getImm();
    256   assert(OffsetOp.isReg() && RegOp.isReg() && "Registers expected.");
    257 
    258   // [ Base OP Offset ]
    259   OS << "[";
    260   if (LPAC::isPreOp(AluCode))
    261     OS << "*";
    262   OS << "%" << getRegisterName(RegOp.getReg());
    263   if (LPAC::isPostOp(AluCode))
    264     OS << "*";
    265   OS << " " << LPAC::lanaiAluCodeToString(AluCode) << " ";
    266   OS << "%" << getRegisterName(OffsetOp.getReg());
    267   OS << "]";
    268 }
    269 
    270 void LanaiInstPrinter::printMemSplsOperand(const MCInst *MI, int OpNo,
    271                                            raw_ostream &OS,
    272                                            const char *Modifier) {
    273   const MCOperand &RegOp = MI->getOperand(OpNo);
    274   const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
    275   const MCOperand &AluOp = MI->getOperand(OpNo + 2);
    276   const unsigned AluCode = AluOp.getImm();
    277 
    278   // Offset
    279   printMemoryImmediateOffset<10>(MAI, OffsetOp, OS);
    280 
    281   // Register
    282   printMemoryBaseRegister(OS, AluCode, RegOp);
    283 }
    284 
    285 void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo,
    286                                       raw_ostream &OS) {
    287   LPCC::CondCode CC =
    288       static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
    289   // Handle the undefined value here for printing so we don't abort().
    290   if (CC >= LPCC::UNKNOWN)
    291     OS << "<und>";
    292   else
    293     OS << lanaiCondCodeToString(CC);
    294 }
    295 
    296 void LanaiInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
    297                                              raw_ostream &OS) {
    298   LPCC::CondCode CC =
    299       static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
    300   // Handle the undefined value here for printing so we don't abort().
    301   if (CC >= LPCC::UNKNOWN)
    302     OS << "<und>";
    303   else if (CC != LPCC::ICC_T)
    304     OS << "." << lanaiCondCodeToString(CC);
    305 }
    306