MipsInstPrinter.cpp revision d5cf5a631fb398d375982fed74196dcd0f7ff952
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/MCSymbol.h" 20#include "llvm/Support/ErrorHandling.h" 21#include "llvm/Support/raw_ostream.h" 22using namespace llvm; 23 24#define GET_INSTRUCTION_NAME 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 getInstructionName(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: assert(0 && "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_GOT: OS << "%got("; break; 100 case MCSymbolRefExpr::VK_Mips_ABS_HI: OS << "%hi("; break; 101 case MCSymbolRefExpr::VK_Mips_ABS_LO: OS << "%lo("; break; 102 case MCSymbolRefExpr::VK_Mips_TLSGD: OS << "%tlsgd("; break; 103 case MCSymbolRefExpr::VK_Mips_GOTTPREL: OS << "%gottprel("; break; 104 case MCSymbolRefExpr::VK_Mips_TPREL_HI: OS << "%tprel_hi("; break; 105 case MCSymbolRefExpr::VK_Mips_TPREL_LO: OS << "%tprel_lo("; break; 106 case MCSymbolRefExpr::VK_Mips_GPOFF_HI: OS << "%hi(%neg(%gp_rel("; break; 107 case MCSymbolRefExpr::VK_Mips_GPOFF_LO: OS << "%lo(%neg(%gp_rel("; break; 108 case MCSymbolRefExpr::VK_Mips_GOT_DISP: OS << "%got_disp("; break; 109 case MCSymbolRefExpr::VK_Mips_GOT_PAGE: OS << "%got_page("; break; 110 case MCSymbolRefExpr::VK_Mips_GOT_OFST: OS << "%got_ofst("; break; 111 } 112 113 OS << SRE->getSymbol(); 114 115 if (Offset) { 116 if (Offset > 0) 117 OS << '+'; 118 OS << Offset; 119 } 120 121 if ((Kind == MCSymbolRefExpr::VK_Mips_GPOFF_HI) || 122 (Kind == MCSymbolRefExpr::VK_Mips_GPOFF_LO)) 123 OS << ")))"; 124 else if (Kind != MCSymbolRefExpr::VK_None) 125 OS << ')'; 126} 127 128void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 129 raw_ostream &O) { 130 const MCOperand &Op = MI->getOperand(OpNo); 131 if (Op.isReg()) { 132 printRegName(O, Op.getReg()); 133 return; 134 } 135 136 if (Op.isImm()) { 137 O << Op.getImm(); 138 return; 139 } 140 141 assert(Op.isExpr() && "unknown operand kind in printOperand"); 142 printExpr(Op.getExpr(), O); 143} 144 145void MipsInstPrinter::printUnsignedImm(const MCInst *MI, int opNum, 146 raw_ostream &O) { 147 const MCOperand &MO = MI->getOperand(opNum); 148 if (MO.isImm()) 149 O << (unsigned short int)MO.getImm(); 150 else 151 printOperand(MI, opNum, O); 152} 153 154void MipsInstPrinter:: 155printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) { 156 // Load/Store memory operands -- imm($reg) 157 // If PIC target the target is loaded as the 158 // pattern lw $25,%call16($28) 159 printOperand(MI, opNum+1, O); 160 O << "("; 161 printOperand(MI, opNum, O); 162 O << ")"; 163} 164 165void MipsInstPrinter:: 166printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O) { 167 // when using stack locations for not load/store instructions 168 // print the same way as all normal 3 operand instructions. 169 printOperand(MI, opNum, O); 170 O << ", "; 171 printOperand(MI, opNum+1, O); 172 return; 173} 174 175void MipsInstPrinter:: 176printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) { 177 const MCOperand& MO = MI->getOperand(opNum); 178 O << MipsFCCToString((Mips::CondCode)MO.getImm()); 179} 180