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