Home | History | Annotate | Download | only in InstPrinter
      1 //===-- MipsInstPrinter.cpp - Convert Mips MCInst to assembly 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 Mips MCInst to a .s file.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #define DEBUG_TYPE "asm-printer"
     15 #include "MipsInstPrinter.h"
     16 #include "MipsInstrInfo.h"
     17 #include "llvm/ADT/StringExtras.h"
     18 #include "llvm/MC/MCExpr.h"
     19 #include "llvm/MC/MCInst.h"
     20 #include "llvm/MC/MCInstrInfo.h"
     21 #include "llvm/MC/MCSymbol.h"
     22 #include "llvm/Support/ErrorHandling.h"
     23 #include "llvm/Support/raw_ostream.h"
     24 using namespace llvm;
     25 
     26 #define PRINT_ALIAS_INSTR
     27 #include "MipsGenAsmWriter.inc"
     28 
     29 const char* Mips::MipsFCCToString(Mips::CondCode CC) {
     30   switch (CC) {
     31   case FCOND_F:
     32   case FCOND_T:   return "f";
     33   case FCOND_UN:
     34   case FCOND_OR:  return "un";
     35   case FCOND_OEQ:
     36   case FCOND_UNE: return "eq";
     37   case FCOND_UEQ:
     38   case FCOND_ONE: return "ueq";
     39   case FCOND_OLT:
     40   case FCOND_UGE: return "olt";
     41   case FCOND_ULT:
     42   case FCOND_OGE: return "ult";
     43   case FCOND_OLE:
     44   case FCOND_UGT: return "ole";
     45   case FCOND_ULE:
     46   case FCOND_OGT: return "ule";
     47   case FCOND_SF:
     48   case FCOND_ST:  return "sf";
     49   case FCOND_NGLE:
     50   case FCOND_GLE: return "ngle";
     51   case FCOND_SEQ:
     52   case FCOND_SNE: return "seq";
     53   case FCOND_NGL:
     54   case FCOND_GL:  return "ngl";
     55   case FCOND_LT:
     56   case FCOND_NLT: return "lt";
     57   case FCOND_NGE:
     58   case FCOND_GE:  return "nge";
     59   case FCOND_LE:
     60   case FCOND_NLE: return "le";
     61   case FCOND_NGT:
     62   case FCOND_GT:  return "ngt";
     63   }
     64   llvm_unreachable("Impossible condition code!");
     65 }
     66 
     67 void MipsInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
     68   OS << '$' << StringRef(getRegisterName(RegNo)).lower();
     69 }
     70 
     71 void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
     72                                 StringRef Annot) {
     73   switch (MI->getOpcode()) {
     74   default:
     75     break;
     76   case Mips::RDHWR:
     77   case Mips::RDHWR64:
     78     O << "\t.set\tpush\n";
     79     O << "\t.set\tmips32r2\n";
     80   }
     81 
     82   // Try to print any aliases first.
     83   if (!printAliasInstr(MI, O))
     84     printInstruction(MI, O);
     85   printAnnotation(O, Annot);
     86 
     87   switch (MI->getOpcode()) {
     88   default:
     89     break;
     90   case Mips::RDHWR:
     91   case Mips::RDHWR64:
     92     O << "\n\t.set\tpop";
     93   }
     94 }
     95 
     96 static void printExpr(const MCExpr *Expr, raw_ostream &OS) {
     97   int Offset = 0;
     98   const MCSymbolRefExpr *SRE;
     99 
    100   if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
    101     SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
    102     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(BE->getRHS());
    103     assert(SRE && CE && "Binary expression must be sym+const.");
    104     Offset = CE->getValue();
    105   }
    106   else if (!(SRE = dyn_cast<MCSymbolRefExpr>(Expr)))
    107     assert(false && "Unexpected MCExpr type.");
    108 
    109   MCSymbolRefExpr::VariantKind Kind = SRE->getKind();
    110 
    111   switch (Kind) {
    112   default:                                 llvm_unreachable("Invalid kind!");
    113   case MCSymbolRefExpr::VK_None:           break;
    114   case MCSymbolRefExpr::VK_Mips_GPREL:     OS << "%gp_rel("; break;
    115   case MCSymbolRefExpr::VK_Mips_GOT_CALL:  OS << "%call16("; break;
    116   case MCSymbolRefExpr::VK_Mips_GOT16:     OS << "%got(";    break;
    117   case MCSymbolRefExpr::VK_Mips_GOT:       OS << "%got(";    break;
    118   case MCSymbolRefExpr::VK_Mips_ABS_HI:    OS << "%hi(";     break;
    119   case MCSymbolRefExpr::VK_Mips_ABS_LO:    OS << "%lo(";     break;
    120   case MCSymbolRefExpr::VK_Mips_TLSGD:     OS << "%tlsgd(";  break;
    121   case MCSymbolRefExpr::VK_Mips_TLSLDM:    OS << "%tlsldm(";  break;
    122   case MCSymbolRefExpr::VK_Mips_DTPREL_HI: OS << "%dtprel_hi(";  break;
    123   case MCSymbolRefExpr::VK_Mips_DTPREL_LO: OS << "%dtprel_lo(";  break;
    124   case MCSymbolRefExpr::VK_Mips_GOTTPREL:  OS << "%gottprel("; break;
    125   case MCSymbolRefExpr::VK_Mips_TPREL_HI:  OS << "%tprel_hi("; break;
    126   case MCSymbolRefExpr::VK_Mips_TPREL_LO:  OS << "%tprel_lo("; break;
    127   case MCSymbolRefExpr::VK_Mips_GPOFF_HI:  OS << "%hi(%neg(%gp_rel("; break;
    128   case MCSymbolRefExpr::VK_Mips_GPOFF_LO:  OS << "%lo(%neg(%gp_rel("; break;
    129   case MCSymbolRefExpr::VK_Mips_GOT_DISP:  OS << "%got_disp("; break;
    130   case MCSymbolRefExpr::VK_Mips_GOT_PAGE:  OS << "%got_page("; break;
    131   case MCSymbolRefExpr::VK_Mips_GOT_OFST:  OS << "%got_ofst("; break;
    132   case MCSymbolRefExpr::VK_Mips_HIGHER:    OS << "%higher("; break;
    133   case MCSymbolRefExpr::VK_Mips_HIGHEST:   OS << "%highest("; break;
    134   case MCSymbolRefExpr::VK_Mips_GOT_HI16:  OS << "%got_hi("; break;
    135   case MCSymbolRefExpr::VK_Mips_GOT_LO16:  OS << "%got_lo("; break;
    136   case MCSymbolRefExpr::VK_Mips_CALL_HI16: OS << "%call_hi("; break;
    137   case MCSymbolRefExpr::VK_Mips_CALL_LO16: OS << "%call_lo("; break;
    138   }
    139 
    140   OS << SRE->getSymbol();
    141 
    142   if (Offset) {
    143     if (Offset > 0)
    144       OS << '+';
    145     OS << Offset;
    146   }
    147 
    148   if ((Kind == MCSymbolRefExpr::VK_Mips_GPOFF_HI) ||
    149       (Kind == MCSymbolRefExpr::VK_Mips_GPOFF_LO))
    150     OS << ")))";
    151   else if (Kind != MCSymbolRefExpr::VK_None)
    152     OS << ')';
    153 }
    154 
    155 void MipsInstPrinter::printCPURegs(const MCInst *MI, unsigned OpNo,
    156                                    raw_ostream &O) {
    157   printRegName(O, MI->getOperand(OpNo).getReg());
    158 }
    159 
    160 void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
    161                                    raw_ostream &O) {
    162   const MCOperand &Op = MI->getOperand(OpNo);
    163   if (Op.isReg()) {
    164     printRegName(O, Op.getReg());
    165     return;
    166   }
    167 
    168   if (Op.isImm()) {
    169     O << Op.getImm();
    170     return;
    171   }
    172 
    173   assert(Op.isExpr() && "unknown operand kind in printOperand");
    174   printExpr(Op.getExpr(), O);
    175 }
    176 
    177 void MipsInstPrinter::printUnsignedImm(const MCInst *MI, int opNum,
    178                                        raw_ostream &O) {
    179   const MCOperand &MO = MI->getOperand(opNum);
    180   if (MO.isImm())
    181     O << (unsigned short int)MO.getImm();
    182   else
    183     printOperand(MI, opNum, O);
    184 }
    185 
    186 void MipsInstPrinter::
    187 printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) {
    188   // Load/Store memory operands -- imm($reg)
    189   // If PIC target the target is loaded as the
    190   // pattern lw $25,%call16($28)
    191   printOperand(MI, opNum+1, O);
    192   O << "(";
    193   printOperand(MI, opNum, O);
    194   O << ")";
    195 }
    196 
    197 void MipsInstPrinter::
    198 printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O) {
    199   // when using stack locations for not load/store instructions
    200   // print the same way as all normal 3 operand instructions.
    201   printOperand(MI, opNum, O);
    202   O << ", ";
    203   printOperand(MI, opNum+1, O);
    204   return;
    205 }
    206 
    207 void MipsInstPrinter::
    208 printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) {
    209   const MCOperand& MO = MI->getOperand(opNum);
    210   O << MipsFCCToString((Mips::CondCode)MO.getImm());
    211 }
    212