SparcInstPrinter.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
1//===-- SparcInstPrinter.cpp - Convert Sparc 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 Sparc MCInst to a .s file. 11// 12//===----------------------------------------------------------------------===// 13 14#define DEBUG_TYPE "asm-printer" 15#include "SparcInstPrinter.h" 16#include "Sparc.h" 17#include "llvm/MC/MCExpr.h" 18#include "llvm/MC/MCInst.h" 19#include "llvm/MC/MCSymbol.h" 20#include "llvm/Support/raw_ostream.h" 21using namespace llvm; 22 23// The generated AsmMatcher SparcGenAsmWriter uses "Sparc" as the target 24// namespace. But SPARC backend uses "SP" as its namespace. 25namespace llvm { 26namespace Sparc { 27 using namespace SP; 28} 29} 30 31#define GET_INSTRUCTION_NAME 32#define PRINT_ALIAS_INSTR 33#include "SparcGenAsmWriter.inc" 34 35bool SparcInstPrinter::isV9() const { 36 return (STI.getFeatureBits() & Sparc::FeatureV9) != 0; 37} 38 39void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const 40{ 41 OS << '%' << StringRef(getRegisterName(RegNo)).lower(); 42} 43 44void SparcInstPrinter::printInst(const MCInst *MI, raw_ostream &O, 45 StringRef Annot) 46{ 47 if (!printAliasInstr(MI, O) && !printSparcAliasInstr(MI, O)) 48 printInstruction(MI, O); 49 printAnnotation(O, Annot); 50} 51 52bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI, raw_ostream &O) 53{ 54 switch (MI->getOpcode()) { 55 default: return false; 56 case SP::JMPLrr: 57 case SP::JMPLri: { 58 if (MI->getNumOperands() != 3) 59 return false; 60 if (!MI->getOperand(0).isReg()) 61 return false; 62 switch (MI->getOperand(0).getReg()) { 63 default: return false; 64 case SP::G0: // jmp $addr | ret | retl 65 if (MI->getOperand(2).isImm() && 66 MI->getOperand(2).getImm() == 8) { 67 switch(MI->getOperand(1).getReg()) { 68 default: break; 69 case SP::I7: O << "\tret"; return true; 70 case SP::O7: O << "\tretl"; return true; 71 } 72 } 73 O << "\tjmp "; printMemOperand(MI, 1, O); 74 return true; 75 case SP::O7: // call $addr 76 O << "\tcall "; printMemOperand(MI, 1, O); 77 return true; 78 } 79 } 80 case SP::V9FCMPS: case SP::V9FCMPD: case SP::V9FCMPQ: 81 case SP::V9FCMPES: case SP::V9FCMPED: case SP::V9FCMPEQ: { 82 if (isV9() 83 || (MI->getNumOperands() != 3) 84 || (!MI->getOperand(0).isReg()) 85 || (MI->getOperand(0).getReg() != SP::FCC0)) 86 return false; 87 // if V8, skip printing %fcc0. 88 switch(MI->getOpcode()) { 89 default: 90 case SP::V9FCMPS: O << "\tfcmps "; break; 91 case SP::V9FCMPD: O << "\tfcmpd "; break; 92 case SP::V9FCMPQ: O << "\tfcmpq "; break; 93 case SP::V9FCMPES: O << "\tfcmpes "; break; 94 case SP::V9FCMPED: O << "\tfcmped "; break; 95 case SP::V9FCMPEQ: O << "\tfcmpeq "; break; 96 } 97 printOperand(MI, 1, O); 98 O << ", "; 99 printOperand(MI, 2, O); 100 return true; 101 } 102 } 103} 104 105void SparcInstPrinter::printOperand(const MCInst *MI, int opNum, 106 raw_ostream &O) 107{ 108 const MCOperand &MO = MI->getOperand (opNum); 109 110 if (MO.isReg()) { 111 printRegName(O, MO.getReg()); 112 return ; 113 } 114 115 if (MO.isImm()) { 116 O << (int)MO.getImm(); 117 return; 118 } 119 120 assert(MO.isExpr() && "Unknown operand kind in printOperand"); 121 MO.getExpr()->print(O); 122} 123 124void SparcInstPrinter::printMemOperand(const MCInst *MI, int opNum, 125 raw_ostream &O, const char *Modifier) 126{ 127 printOperand(MI, opNum, O); 128 129 // If this is an ADD operand, emit it like normal operands. 130 if (Modifier && !strcmp(Modifier, "arith")) { 131 O << ", "; 132 printOperand(MI, opNum+1, O); 133 return; 134 } 135 const MCOperand &MO = MI->getOperand(opNum+1); 136 137 if (MO.isReg() && MO.getReg() == SP::G0) 138 return; // don't print "+%g0" 139 if (MO.isImm() && MO.getImm() == 0) 140 return; // don't print "+0" 141 142 O << "+"; 143 144 printOperand(MI, opNum+1, O); 145} 146 147void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum, 148 raw_ostream &O) 149{ 150 int CC = (int)MI->getOperand(opNum).getImm(); 151 switch (MI->getOpcode()) { 152 default: break; 153 case SP::FBCOND: 154 case SP::FBCONDA: 155 case SP::BPFCC: 156 case SP::BPFCCA: 157 case SP::BPFCCNT: 158 case SP::BPFCCANT: 159 case SP::MOVFCCrr: case SP::V9MOVFCCrr: 160 case SP::MOVFCCri: case SP::V9MOVFCCri: 161 case SP::FMOVS_FCC: case SP::V9FMOVS_FCC: 162 case SP::FMOVD_FCC: case SP::V9FMOVD_FCC: 163 case SP::FMOVQ_FCC: case SP::V9FMOVQ_FCC: 164 // Make sure CC is a fp conditional flag. 165 CC = (CC < 16) ? (CC + 16) : CC; 166 break; 167 } 168 O << SPARCCondCodeToString((SPCC::CondCodes)CC); 169} 170 171bool SparcInstPrinter::printGetPCX(const MCInst *MI, unsigned opNum, 172 raw_ostream &O) 173{ 174 assert(0 && "FIXME: Implement SparcInstPrinter::printGetPCX."); 175 return true; 176} 177