LLVM API Documentation

MipsInstPrinter.cpp
Go to the documentation of this file.
00001 //===-- MipsInstPrinter.cpp - Convert Mips MCInst to assembly syntax ------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This class prints an Mips MCInst to a .s file.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "MipsInstPrinter.h"
00015 #include "MCTargetDesc/MipsMCExpr.h"
00016 #include "MipsInstrInfo.h"
00017 #include "llvm/ADT/StringExtras.h"
00018 #include "llvm/MC/MCExpr.h"
00019 #include "llvm/MC/MCInst.h"
00020 #include "llvm/MC/MCInstrInfo.h"
00021 #include "llvm/MC/MCSymbol.h"
00022 #include "llvm/Support/ErrorHandling.h"
00023 #include "llvm/Support/raw_ostream.h"
00024 using namespace llvm;
00025 
00026 #define DEBUG_TYPE "asm-printer"
00027 
00028 #define PRINT_ALIAS_INSTR
00029 #include "MipsGenAsmWriter.inc"
00030 
00031 template<unsigned R>
00032 static bool isReg(const MCInst &MI, unsigned OpNo) {
00033   assert(MI.getOperand(OpNo).isReg() && "Register operand expected.");
00034   return MI.getOperand(OpNo).getReg() == R;
00035 }
00036 
00037 const char* Mips::MipsFCCToString(Mips::CondCode CC) {
00038   switch (CC) {
00039   case FCOND_F:
00040   case FCOND_T:   return "f";
00041   case FCOND_UN:
00042   case FCOND_OR:  return "un";
00043   case FCOND_OEQ:
00044   case FCOND_UNE: return "eq";
00045   case FCOND_UEQ:
00046   case FCOND_ONE: return "ueq";
00047   case FCOND_OLT:
00048   case FCOND_UGE: return "olt";
00049   case FCOND_ULT:
00050   case FCOND_OGE: return "ult";
00051   case FCOND_OLE:
00052   case FCOND_UGT: return "ole";
00053   case FCOND_ULE:
00054   case FCOND_OGT: return "ule";
00055   case FCOND_SF:
00056   case FCOND_ST:  return "sf";
00057   case FCOND_NGLE:
00058   case FCOND_GLE: return "ngle";
00059   case FCOND_SEQ:
00060   case FCOND_SNE: return "seq";
00061   case FCOND_NGL:
00062   case FCOND_GL:  return "ngl";
00063   case FCOND_LT:
00064   case FCOND_NLT: return "lt";
00065   case FCOND_NGE:
00066   case FCOND_GE:  return "nge";
00067   case FCOND_LE:
00068   case FCOND_NLE: return "le";
00069   case FCOND_NGT:
00070   case FCOND_GT:  return "ngt";
00071   }
00072   llvm_unreachable("Impossible condition code!");
00073 }
00074 
00075 void MipsInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
00076   OS << '$' << StringRef(getRegisterName(RegNo)).lower();
00077 }
00078 
00079 void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
00080                                 StringRef Annot) {
00081   switch (MI->getOpcode()) {
00082   default:
00083     break;
00084   case Mips::RDHWR:
00085   case Mips::RDHWR64:
00086     O << "\t.set\tpush\n";
00087     O << "\t.set\tmips32r2\n";
00088     break;
00089   case Mips::Save16:
00090     O << "\tsave\t";
00091     printSaveRestore(MI, O);
00092     O << " # 16 bit inst\n";
00093     return;
00094   case Mips::SaveX16:
00095     O << "\tsave\t";
00096     printSaveRestore(MI, O);
00097     O << "\n";
00098     return;
00099   case Mips::Restore16:
00100     O << "\trestore\t";
00101     printSaveRestore(MI, O);
00102     O << " # 16 bit inst\n";
00103     return;
00104   case Mips::RestoreX16:
00105     O << "\trestore\t";
00106     printSaveRestore(MI, O);
00107     O << "\n";
00108     return;
00109   }
00110 
00111   // Try to print any aliases first.
00112   if (!printAliasInstr(MI, O) && !printAlias(*MI, O))
00113     printInstruction(MI, O);
00114   printAnnotation(O, Annot);
00115 
00116   switch (MI->getOpcode()) {
00117   default:
00118     break;
00119   case Mips::RDHWR:
00120   case Mips::RDHWR64:
00121     O << "\n\t.set\tpop";
00122   }
00123 }
00124 
00125 static void printExpr(const MCExpr *Expr, raw_ostream &OS) {
00126   int Offset = 0;
00127   const MCSymbolRefExpr *SRE;
00128 
00129   if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
00130     SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
00131     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(BE->getRHS());
00132     assert(SRE && CE && "Binary expression must be sym+const.");
00133     Offset = CE->getValue();
00134   } else if (const MipsMCExpr *ME = dyn_cast<MipsMCExpr>(Expr)) {
00135     ME->print(OS);
00136     return;
00137   } else if (!(SRE = dyn_cast<MCSymbolRefExpr>(Expr)))
00138     assert(false && "Unexpected MCExpr type.");
00139 
00140   MCSymbolRefExpr::VariantKind Kind = SRE->getKind();
00141 
00142   switch (Kind) {
00143   default:                                 llvm_unreachable("Invalid kind!");
00144   case MCSymbolRefExpr::VK_None:           break;
00145   case MCSymbolRefExpr::VK_Mips_GPREL:     OS << "%gp_rel("; break;
00146   case MCSymbolRefExpr::VK_Mips_GOT_CALL:  OS << "%call16("; break;
00147   case MCSymbolRefExpr::VK_Mips_GOT16:     OS << "%got(";    break;
00148   case MCSymbolRefExpr::VK_Mips_GOT:       OS << "%got(";    break;
00149   case MCSymbolRefExpr::VK_Mips_ABS_HI:    OS << "%hi(";     break;
00150   case MCSymbolRefExpr::VK_Mips_ABS_LO:    OS << "%lo(";     break;
00151   case MCSymbolRefExpr::VK_Mips_TLSGD:     OS << "%tlsgd(";  break;
00152   case MCSymbolRefExpr::VK_Mips_TLSLDM:    OS << "%tlsldm(";  break;
00153   case MCSymbolRefExpr::VK_Mips_DTPREL_HI: OS << "%dtprel_hi(";  break;
00154   case MCSymbolRefExpr::VK_Mips_DTPREL_LO: OS << "%dtprel_lo(";  break;
00155   case MCSymbolRefExpr::VK_Mips_GOTTPREL:  OS << "%gottprel("; break;
00156   case MCSymbolRefExpr::VK_Mips_TPREL_HI:  OS << "%tprel_hi("; break;
00157   case MCSymbolRefExpr::VK_Mips_TPREL_LO:  OS << "%tprel_lo("; break;
00158   case MCSymbolRefExpr::VK_Mips_GPOFF_HI:  OS << "%hi(%neg(%gp_rel("; break;
00159   case MCSymbolRefExpr::VK_Mips_GPOFF_LO:  OS << "%lo(%neg(%gp_rel("; break;
00160   case MCSymbolRefExpr::VK_Mips_GOT_DISP:  OS << "%got_disp("; break;
00161   case MCSymbolRefExpr::VK_Mips_GOT_PAGE:  OS << "%got_page("; break;
00162   case MCSymbolRefExpr::VK_Mips_GOT_OFST:  OS << "%got_ofst("; break;
00163   case MCSymbolRefExpr::VK_Mips_HIGHER:    OS << "%higher("; break;
00164   case MCSymbolRefExpr::VK_Mips_HIGHEST:   OS << "%highest("; break;
00165   case MCSymbolRefExpr::VK_Mips_GOT_HI16:  OS << "%got_hi("; break;
00166   case MCSymbolRefExpr::VK_Mips_GOT_LO16:  OS << "%got_lo("; break;
00167   case MCSymbolRefExpr::VK_Mips_CALL_HI16: OS << "%call_hi("; break;
00168   case MCSymbolRefExpr::VK_Mips_CALL_LO16: OS << "%call_lo("; break;
00169   case MCSymbolRefExpr::VK_Mips_PCREL_HI16: OS << "%pcrel_hi("; break;
00170   case MCSymbolRefExpr::VK_Mips_PCREL_LO16: OS << "%pcrel_lo("; break;
00171   }
00172 
00173   OS << SRE->getSymbol();
00174 
00175   if (Offset) {
00176     if (Offset > 0)
00177       OS << '+';
00178     OS << Offset;
00179   }
00180 
00181   if ((Kind == MCSymbolRefExpr::VK_Mips_GPOFF_HI) ||
00182       (Kind == MCSymbolRefExpr::VK_Mips_GPOFF_LO))
00183     OS << ")))";
00184   else if (Kind != MCSymbolRefExpr::VK_None)
00185     OS << ')';
00186 }
00187 
00188 void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
00189                                    raw_ostream &O) {
00190   const MCOperand &Op = MI->getOperand(OpNo);
00191   if (Op.isReg()) {
00192     printRegName(O, Op.getReg());
00193     return;
00194   }
00195 
00196   if (Op.isImm()) {
00197     O << Op.getImm();
00198     return;
00199   }
00200 
00201   assert(Op.isExpr() && "unknown operand kind in printOperand");
00202   printExpr(Op.getExpr(), O);
00203 }
00204 
00205 void MipsInstPrinter::printUnsignedImm(const MCInst *MI, int opNum,
00206                                        raw_ostream &O) {
00207   const MCOperand &MO = MI->getOperand(opNum);
00208   if (MO.isImm())
00209     O << (unsigned short int)MO.getImm();
00210   else
00211     printOperand(MI, opNum, O);
00212 }
00213 
00214 void MipsInstPrinter::printUnsignedImm8(const MCInst *MI, int opNum,
00215                                         raw_ostream &O) {
00216   const MCOperand &MO = MI->getOperand(opNum);
00217   if (MO.isImm())
00218     O << (unsigned short int)(unsigned char)MO.getImm();
00219   else
00220     printOperand(MI, opNum, O);
00221 }
00222 
00223 void MipsInstPrinter::
00224 printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) {
00225   // Load/Store memory operands -- imm($reg)
00226   // If PIC target the target is loaded as the
00227   // pattern lw $25,%call16($28)
00228   printOperand(MI, opNum+1, O);
00229   O << "(";
00230   printOperand(MI, opNum, O);
00231   O << ")";
00232 }
00233 
00234 void MipsInstPrinter::
00235 printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O) {
00236   // when using stack locations for not load/store instructions
00237   // print the same way as all normal 3 operand instructions.
00238   printOperand(MI, opNum, O);
00239   O << ", ";
00240   printOperand(MI, opNum+1, O);
00241   return;
00242 }
00243 
00244 void MipsInstPrinter::
00245 printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) {
00246   const MCOperand& MO = MI->getOperand(opNum);
00247   O << MipsFCCToString((Mips::CondCode)MO.getImm());
00248 }
00249 
00250 void MipsInstPrinter::
00251 printSHFMask(const MCInst *MI, int opNum, raw_ostream &O) {
00252   llvm_unreachable("TODO");
00253 }
00254 
00255 bool MipsInstPrinter::printAlias(const char *Str, const MCInst &MI,
00256                                  unsigned OpNo, raw_ostream &OS) {
00257   OS << "\t" << Str << "\t";
00258   printOperand(&MI, OpNo, OS);
00259   return true;
00260 }
00261 
00262 bool MipsInstPrinter::printAlias(const char *Str, const MCInst &MI,
00263                                  unsigned OpNo0, unsigned OpNo1,
00264                                  raw_ostream &OS) {
00265   printAlias(Str, MI, OpNo0, OS);
00266   OS << ", ";
00267   printOperand(&MI, OpNo1, OS);
00268   return true;
00269 }
00270 
00271 bool MipsInstPrinter::printAlias(const MCInst &MI, raw_ostream &OS) {
00272   switch (MI.getOpcode()) {
00273   case Mips::BEQ:
00274     // beq $zero, $zero, $L2 => b $L2
00275     // beq $r0, $zero, $L2 => beqz $r0, $L2
00276     return (isReg<Mips::ZERO>(MI, 0) && isReg<Mips::ZERO>(MI, 1) &&
00277             printAlias("b", MI, 2, OS)) ||
00278            (isReg<Mips::ZERO>(MI, 1) && printAlias("beqz", MI, 0, 2, OS));
00279   case Mips::BEQ64:
00280     // beq $r0, $zero, $L2 => beqz $r0, $L2
00281     return isReg<Mips::ZERO_64>(MI, 1) && printAlias("beqz", MI, 0, 2, OS);
00282   case Mips::BNE:
00283     // bne $r0, $zero, $L2 => bnez $r0, $L2
00284     return isReg<Mips::ZERO>(MI, 1) && printAlias("bnez", MI, 0, 2, OS);
00285   case Mips::BNE64:
00286     // bne $r0, $zero, $L2 => bnez $r0, $L2
00287     return isReg<Mips::ZERO_64>(MI, 1) && printAlias("bnez", MI, 0, 2, OS);
00288   case Mips::BGEZAL:
00289     // bgezal $zero, $L1 => bal $L1
00290     return isReg<Mips::ZERO>(MI, 0) && printAlias("bal", MI, 1, OS);
00291   case Mips::BC1T:
00292     // bc1t $fcc0, $L1 => bc1t $L1
00293     return isReg<Mips::FCC0>(MI, 0) && printAlias("bc1t", MI, 1, OS);
00294   case Mips::BC1F:
00295     // bc1f $fcc0, $L1 => bc1f $L1
00296     return isReg<Mips::FCC0>(MI, 0) && printAlias("bc1f", MI, 1, OS);
00297   case Mips::JALR:
00298     // jalr $ra, $r1 => jalr $r1
00299     return isReg<Mips::RA>(MI, 0) && printAlias("jalr", MI, 1, OS);
00300   case Mips::JALR64:
00301     // jalr $ra, $r1 => jalr $r1
00302     return isReg<Mips::RA_64>(MI, 0) && printAlias("jalr", MI, 1, OS);
00303   case Mips::NOR:
00304   case Mips::NOR_MM:
00305     // nor $r0, $r1, $zero => not $r0, $r1
00306     return isReg<Mips::ZERO>(MI, 2) && printAlias("not", MI, 0, 1, OS);
00307   case Mips::NOR64:
00308     // nor $r0, $r1, $zero => not $r0, $r1
00309     return isReg<Mips::ZERO_64>(MI, 2) && printAlias("not", MI, 0, 1, OS);
00310   case Mips::OR:
00311     // or $r0, $r1, $zero => move $r0, $r1
00312     return isReg<Mips::ZERO>(MI, 2) && printAlias("move", MI, 0, 1, OS);
00313   default: return false;
00314   }
00315 }
00316 
00317 void MipsInstPrinter::printSaveRestore(const MCInst *MI, raw_ostream &O) {
00318   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
00319     if (i != 0) O << ", ";
00320     if (MI->getOperand(i).isReg())
00321       printRegName(O, MI->getOperand(i).getReg());
00322     else
00323       printUnsignedImm(MI, i, O);
00324   }
00325 }
00326