MipsInstPrinter.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
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 "MCTargetDesc/MipsMCExpr.h" 17#include "MipsInstrInfo.h" 18#include "llvm/ADT/StringExtras.h" 19#include "llvm/MC/MCExpr.h" 20#include "llvm/MC/MCInst.h" 21#include "llvm/MC/MCInstrInfo.h" 22#include "llvm/MC/MCSymbol.h" 23#include "llvm/Support/ErrorHandling.h" 24#include "llvm/Support/raw_ostream.h" 25using namespace llvm; 26 27#define PRINT_ALIAS_INSTR 28#include "MipsGenAsmWriter.inc" 29 30template<unsigned R> 31static bool isReg(const MCInst &MI, unsigned OpNo) { 32 assert(MI.getOperand(OpNo).isReg() && "Register operand expected."); 33 return MI.getOperand(OpNo).getReg() == R; 34} 35 36const char* Mips::MipsFCCToString(Mips::CondCode CC) { 37 switch (CC) { 38 case FCOND_F: 39 case FCOND_T: return "f"; 40 case FCOND_UN: 41 case FCOND_OR: return "un"; 42 case FCOND_OEQ: 43 case FCOND_UNE: return "eq"; 44 case FCOND_UEQ: 45 case FCOND_ONE: return "ueq"; 46 case FCOND_OLT: 47 case FCOND_UGE: return "olt"; 48 case FCOND_ULT: 49 case FCOND_OGE: return "ult"; 50 case FCOND_OLE: 51 case FCOND_UGT: return "ole"; 52 case FCOND_ULE: 53 case FCOND_OGT: return "ule"; 54 case FCOND_SF: 55 case FCOND_ST: return "sf"; 56 case FCOND_NGLE: 57 case FCOND_GLE: return "ngle"; 58 case FCOND_SEQ: 59 case FCOND_SNE: return "seq"; 60 case FCOND_NGL: 61 case FCOND_GL: return "ngl"; 62 case FCOND_LT: 63 case FCOND_NLT: return "lt"; 64 case FCOND_NGE: 65 case FCOND_GE: return "nge"; 66 case FCOND_LE: 67 case FCOND_NLE: return "le"; 68 case FCOND_NGT: 69 case FCOND_GT: return "ngt"; 70 } 71 llvm_unreachable("Impossible condition code!"); 72} 73 74void MipsInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { 75 OS << '$' << StringRef(getRegisterName(RegNo)).lower(); 76} 77 78void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O, 79 StringRef Annot) { 80 switch (MI->getOpcode()) { 81 default: 82 break; 83 case Mips::RDHWR: 84 case Mips::RDHWR64: 85 O << "\t.set\tpush\n"; 86 O << "\t.set\tmips32r2\n"; 87 break; 88 case Mips::Save16: 89 O << "\tsave\t"; 90 printSaveRestore(MI, O); 91 O << " # 16 bit inst\n"; 92 return; 93 case Mips::SaveX16: 94 O << "\tsave\t"; 95 printSaveRestore(MI, O); 96 O << "\n"; 97 return; 98 case Mips::Restore16: 99 O << "\trestore\t"; 100 printSaveRestore(MI, O); 101 O << " # 16 bit inst\n"; 102 return; 103 case Mips::RestoreX16: 104 O << "\trestore\t"; 105 printSaveRestore(MI, O); 106 O << "\n"; 107 return; 108 } 109 110 // Try to print any aliases first. 111 if (!printAliasInstr(MI, O) && !printAlias(*MI, O)) 112 printInstruction(MI, O); 113 printAnnotation(O, Annot); 114 115 switch (MI->getOpcode()) { 116 default: 117 break; 118 case Mips::RDHWR: 119 case Mips::RDHWR64: 120 O << "\n\t.set\tpop"; 121 } 122} 123 124static void printExpr(const MCExpr *Expr, raw_ostream &OS) { 125 int Offset = 0; 126 const MCSymbolRefExpr *SRE; 127 128 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) { 129 SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS()); 130 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(BE->getRHS()); 131 assert(SRE && CE && "Binary expression must be sym+const."); 132 Offset = CE->getValue(); 133 } else if (const MipsMCExpr *ME = dyn_cast<MipsMCExpr>(Expr)) { 134 ME->print(OS); 135 return; 136 } else if (!(SRE = dyn_cast<MCSymbolRefExpr>(Expr))) 137 assert(false && "Unexpected MCExpr type."); 138 139 MCSymbolRefExpr::VariantKind Kind = SRE->getKind(); 140 141 switch (Kind) { 142 default: llvm_unreachable("Invalid kind!"); 143 case MCSymbolRefExpr::VK_None: break; 144 case MCSymbolRefExpr::VK_Mips_GPREL: OS << "%gp_rel("; break; 145 case MCSymbolRefExpr::VK_Mips_GOT_CALL: OS << "%call16("; break; 146 case MCSymbolRefExpr::VK_Mips_GOT16: OS << "%got("; break; 147 case MCSymbolRefExpr::VK_Mips_GOT: OS << "%got("; break; 148 case MCSymbolRefExpr::VK_Mips_ABS_HI: OS << "%hi("; break; 149 case MCSymbolRefExpr::VK_Mips_ABS_LO: OS << "%lo("; break; 150 case MCSymbolRefExpr::VK_Mips_TLSGD: OS << "%tlsgd("; break; 151 case MCSymbolRefExpr::VK_Mips_TLSLDM: OS << "%tlsldm("; break; 152 case MCSymbolRefExpr::VK_Mips_DTPREL_HI: OS << "%dtprel_hi("; break; 153 case MCSymbolRefExpr::VK_Mips_DTPREL_LO: OS << "%dtprel_lo("; break; 154 case MCSymbolRefExpr::VK_Mips_GOTTPREL: OS << "%gottprel("; break; 155 case MCSymbolRefExpr::VK_Mips_TPREL_HI: OS << "%tprel_hi("; break; 156 case MCSymbolRefExpr::VK_Mips_TPREL_LO: OS << "%tprel_lo("; break; 157 case MCSymbolRefExpr::VK_Mips_GPOFF_HI: OS << "%hi(%neg(%gp_rel("; break; 158 case MCSymbolRefExpr::VK_Mips_GPOFF_LO: OS << "%lo(%neg(%gp_rel("; break; 159 case MCSymbolRefExpr::VK_Mips_GOT_DISP: OS << "%got_disp("; break; 160 case MCSymbolRefExpr::VK_Mips_GOT_PAGE: OS << "%got_page("; break; 161 case MCSymbolRefExpr::VK_Mips_GOT_OFST: OS << "%got_ofst("; break; 162 case MCSymbolRefExpr::VK_Mips_HIGHER: OS << "%higher("; break; 163 case MCSymbolRefExpr::VK_Mips_HIGHEST: OS << "%highest("; break; 164 case MCSymbolRefExpr::VK_Mips_GOT_HI16: OS << "%got_hi("; break; 165 case MCSymbolRefExpr::VK_Mips_GOT_LO16: OS << "%got_lo("; break; 166 case MCSymbolRefExpr::VK_Mips_CALL_HI16: OS << "%call_hi("; break; 167 case MCSymbolRefExpr::VK_Mips_CALL_LO16: OS << "%call_lo("; break; 168 } 169 170 OS << SRE->getSymbol(); 171 172 if (Offset) { 173 if (Offset > 0) 174 OS << '+'; 175 OS << Offset; 176 } 177 178 if ((Kind == MCSymbolRefExpr::VK_Mips_GPOFF_HI) || 179 (Kind == MCSymbolRefExpr::VK_Mips_GPOFF_LO)) 180 OS << ")))"; 181 else if (Kind != MCSymbolRefExpr::VK_None) 182 OS << ')'; 183} 184 185void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 186 raw_ostream &O) { 187 const MCOperand &Op = MI->getOperand(OpNo); 188 if (Op.isReg()) { 189 printRegName(O, Op.getReg()); 190 return; 191 } 192 193 if (Op.isImm()) { 194 O << Op.getImm(); 195 return; 196 } 197 198 assert(Op.isExpr() && "unknown operand kind in printOperand"); 199 printExpr(Op.getExpr(), O); 200} 201 202void MipsInstPrinter::printUnsignedImm(const MCInst *MI, int opNum, 203 raw_ostream &O) { 204 const MCOperand &MO = MI->getOperand(opNum); 205 if (MO.isImm()) 206 O << (unsigned short int)MO.getImm(); 207 else 208 printOperand(MI, opNum, O); 209} 210 211void MipsInstPrinter::printUnsignedImm8(const MCInst *MI, int opNum, 212 raw_ostream &O) { 213 const MCOperand &MO = MI->getOperand(opNum); 214 if (MO.isImm()) 215 O << (unsigned short int)(unsigned char)MO.getImm(); 216 else 217 printOperand(MI, opNum, O); 218} 219 220void MipsInstPrinter:: 221printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) { 222 // Load/Store memory operands -- imm($reg) 223 // If PIC target the target is loaded as the 224 // pattern lw $25,%call16($28) 225 printOperand(MI, opNum+1, O); 226 O << "("; 227 printOperand(MI, opNum, O); 228 O << ")"; 229} 230 231void MipsInstPrinter:: 232printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O) { 233 // when using stack locations for not load/store instructions 234 // print the same way as all normal 3 operand instructions. 235 printOperand(MI, opNum, O); 236 O << ", "; 237 printOperand(MI, opNum+1, O); 238 return; 239} 240 241void MipsInstPrinter:: 242printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) { 243 const MCOperand& MO = MI->getOperand(opNum); 244 O << MipsFCCToString((Mips::CondCode)MO.getImm()); 245} 246 247void MipsInstPrinter:: 248printSHFMask(const MCInst *MI, int opNum, raw_ostream &O) { 249 llvm_unreachable("TODO"); 250} 251 252bool MipsInstPrinter::printAlias(const char *Str, const MCInst &MI, 253 unsigned OpNo, raw_ostream &OS) { 254 OS << "\t" << Str << "\t"; 255 printOperand(&MI, OpNo, OS); 256 return true; 257} 258 259bool MipsInstPrinter::printAlias(const char *Str, const MCInst &MI, 260 unsigned OpNo0, unsigned OpNo1, 261 raw_ostream &OS) { 262 printAlias(Str, MI, OpNo0, OS); 263 OS << ", "; 264 printOperand(&MI, OpNo1, OS); 265 return true; 266} 267 268bool MipsInstPrinter::printAlias(const MCInst &MI, raw_ostream &OS) { 269 switch (MI.getOpcode()) { 270 case Mips::BEQ: 271 // beq $zero, $zero, $L2 => b $L2 272 // beq $r0, $zero, $L2 => beqz $r0, $L2 273 return (isReg<Mips::ZERO>(MI, 0) && isReg<Mips::ZERO>(MI, 1) && 274 printAlias("b", MI, 2, OS)) || 275 (isReg<Mips::ZERO>(MI, 1) && printAlias("beqz", MI, 0, 2, OS)); 276 case Mips::BEQ64: 277 // beq $r0, $zero, $L2 => beqz $r0, $L2 278 return isReg<Mips::ZERO_64>(MI, 1) && printAlias("beqz", MI, 0, 2, OS); 279 case Mips::BNE: 280 // bne $r0, $zero, $L2 => bnez $r0, $L2 281 return isReg<Mips::ZERO>(MI, 1) && printAlias("bnez", MI, 0, 2, OS); 282 case Mips::BNE64: 283 // bne $r0, $zero, $L2 => bnez $r0, $L2 284 return isReg<Mips::ZERO_64>(MI, 1) && printAlias("bnez", MI, 0, 2, OS); 285 case Mips::BGEZAL: 286 // bgezal $zero, $L1 => bal $L1 287 return isReg<Mips::ZERO>(MI, 0) && printAlias("bal", MI, 1, OS); 288 case Mips::BC1T: 289 // bc1t $fcc0, $L1 => bc1t $L1 290 return isReg<Mips::FCC0>(MI, 0) && printAlias("bc1t", MI, 1, OS); 291 case Mips::BC1F: 292 // bc1f $fcc0, $L1 => bc1f $L1 293 return isReg<Mips::FCC0>(MI, 0) && printAlias("bc1f", MI, 1, OS); 294 case Mips::JALR: 295 // jalr $ra, $r1 => jalr $r1 296 return isReg<Mips::RA>(MI, 0) && printAlias("jalr", MI, 1, OS); 297 case Mips::JALR64: 298 // jalr $ra, $r1 => jalr $r1 299 return isReg<Mips::RA_64>(MI, 0) && printAlias("jalr", MI, 1, OS); 300 case Mips::NOR: 301 case Mips::NOR_MM: 302 // nor $r0, $r1, $zero => not $r0, $r1 303 return isReg<Mips::ZERO>(MI, 2) && printAlias("not", MI, 0, 1, OS); 304 case Mips::NOR64: 305 // nor $r0, $r1, $zero => not $r0, $r1 306 return isReg<Mips::ZERO_64>(MI, 2) && printAlias("not", MI, 0, 1, OS); 307 case Mips::OR: 308 // or $r0, $r1, $zero => move $r0, $r1 309 return isReg<Mips::ZERO>(MI, 2) && printAlias("move", MI, 0, 1, OS); 310 default: return false; 311 } 312} 313 314void MipsInstPrinter::printSaveRestore(const MCInst *MI, raw_ostream &O) { 315 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 316 if (i != 0) O << ", "; 317 if (MI->getOperand(i).isReg()) 318 printRegName(O, MI->getOperand(i).getReg()); 319 else 320 printUnsignedImm(MI, i, O); 321 } 322} 323 324