LLVM API Documentation
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