LLVM API Documentation
00001 //===-- SparcInstPrinter.cpp - Convert Sparc 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 Sparc MCInst to a .s file. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "SparcInstPrinter.h" 00015 #include "Sparc.h" 00016 #include "llvm/MC/MCExpr.h" 00017 #include "llvm/MC/MCInst.h" 00018 #include "llvm/MC/MCRegisterInfo.h" 00019 #include "llvm/MC/MCSymbol.h" 00020 #include "llvm/Support/raw_ostream.h" 00021 using namespace llvm; 00022 00023 #define DEBUG_TYPE "asm-printer" 00024 00025 // The generated AsmMatcher SparcGenAsmWriter uses "Sparc" as the target 00026 // namespace. But SPARC backend uses "SP" as its namespace. 00027 namespace llvm { 00028 namespace Sparc { 00029 using namespace SP; 00030 } 00031 } 00032 00033 #define GET_INSTRUCTION_NAME 00034 #define PRINT_ALIAS_INSTR 00035 #include "SparcGenAsmWriter.inc" 00036 00037 bool SparcInstPrinter::isV9() const { 00038 return (STI.getFeatureBits() & Sparc::FeatureV9) != 0; 00039 } 00040 00041 void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const 00042 { 00043 OS << '%' << StringRef(getRegisterName(RegNo)).lower(); 00044 } 00045 00046 void SparcInstPrinter::printInst(const MCInst *MI, raw_ostream &O, 00047 StringRef Annot) 00048 { 00049 if (!printAliasInstr(MI, O) && !printSparcAliasInstr(MI, O)) 00050 printInstruction(MI, O); 00051 printAnnotation(O, Annot); 00052 } 00053 00054 bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI, raw_ostream &O) 00055 { 00056 switch (MI->getOpcode()) { 00057 default: return false; 00058 case SP::JMPLrr: 00059 case SP::JMPLri: { 00060 if (MI->getNumOperands() != 3) 00061 return false; 00062 if (!MI->getOperand(0).isReg()) 00063 return false; 00064 switch (MI->getOperand(0).getReg()) { 00065 default: return false; 00066 case SP::G0: // jmp $addr | ret | retl 00067 if (MI->getOperand(2).isImm() && 00068 MI->getOperand(2).getImm() == 8) { 00069 switch(MI->getOperand(1).getReg()) { 00070 default: break; 00071 case SP::I7: O << "\tret"; return true; 00072 case SP::O7: O << "\tretl"; return true; 00073 } 00074 } 00075 O << "\tjmp "; printMemOperand(MI, 1, O); 00076 return true; 00077 case SP::O7: // call $addr 00078 O << "\tcall "; printMemOperand(MI, 1, O); 00079 return true; 00080 } 00081 } 00082 case SP::V9FCMPS: case SP::V9FCMPD: case SP::V9FCMPQ: 00083 case SP::V9FCMPES: case SP::V9FCMPED: case SP::V9FCMPEQ: { 00084 if (isV9() 00085 || (MI->getNumOperands() != 3) 00086 || (!MI->getOperand(0).isReg()) 00087 || (MI->getOperand(0).getReg() != SP::FCC0)) 00088 return false; 00089 // if V8, skip printing %fcc0. 00090 switch(MI->getOpcode()) { 00091 default: 00092 case SP::V9FCMPS: O << "\tfcmps "; break; 00093 case SP::V9FCMPD: O << "\tfcmpd "; break; 00094 case SP::V9FCMPQ: O << "\tfcmpq "; break; 00095 case SP::V9FCMPES: O << "\tfcmpes "; break; 00096 case SP::V9FCMPED: O << "\tfcmped "; break; 00097 case SP::V9FCMPEQ: O << "\tfcmpeq "; break; 00098 } 00099 printOperand(MI, 1, O); 00100 O << ", "; 00101 printOperand(MI, 2, O); 00102 return true; 00103 } 00104 } 00105 } 00106 00107 void SparcInstPrinter::printOperand(const MCInst *MI, int opNum, 00108 raw_ostream &O) 00109 { 00110 const MCOperand &MO = MI->getOperand (opNum); 00111 00112 if (MO.isReg()) { 00113 printRegName(O, MO.getReg()); 00114 return ; 00115 } 00116 00117 if (MO.isImm()) { 00118 O << (int)MO.getImm(); 00119 return; 00120 } 00121 00122 assert(MO.isExpr() && "Unknown operand kind in printOperand"); 00123 MO.getExpr()->print(O); 00124 } 00125 00126 void SparcInstPrinter::printMemOperand(const MCInst *MI, int opNum, 00127 raw_ostream &O, const char *Modifier) 00128 { 00129 printOperand(MI, opNum, O); 00130 00131 // If this is an ADD operand, emit it like normal operands. 00132 if (Modifier && !strcmp(Modifier, "arith")) { 00133 O << ", "; 00134 printOperand(MI, opNum+1, O); 00135 return; 00136 } 00137 const MCOperand &MO = MI->getOperand(opNum+1); 00138 00139 if (MO.isReg() && MO.getReg() == SP::G0) 00140 return; // don't print "+%g0" 00141 if (MO.isImm() && MO.getImm() == 0) 00142 return; // don't print "+0" 00143 00144 O << "+"; 00145 00146 printOperand(MI, opNum+1, O); 00147 } 00148 00149 void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum, 00150 raw_ostream &O) 00151 { 00152 int CC = (int)MI->getOperand(opNum).getImm(); 00153 switch (MI->getOpcode()) { 00154 default: break; 00155 case SP::FBCOND: 00156 case SP::FBCONDA: 00157 case SP::BPFCC: 00158 case SP::BPFCCA: 00159 case SP::BPFCCNT: 00160 case SP::BPFCCANT: 00161 case SP::MOVFCCrr: case SP::V9MOVFCCrr: 00162 case SP::MOVFCCri: case SP::V9MOVFCCri: 00163 case SP::FMOVS_FCC: case SP::V9FMOVS_FCC: 00164 case SP::FMOVD_FCC: case SP::V9FMOVD_FCC: 00165 case SP::FMOVQ_FCC: case SP::V9FMOVQ_FCC: 00166 // Make sure CC is a fp conditional flag. 00167 CC = (CC < 16) ? (CC + 16) : CC; 00168 break; 00169 } 00170 O << SPARCCondCodeToString((SPCC::CondCodes)CC); 00171 } 00172 00173 bool SparcInstPrinter::printGetPCX(const MCInst *MI, unsigned opNum, 00174 raw_ostream &O) 00175 { 00176 llvm_unreachable("FIXME: Implement SparcInstPrinter::printGetPCX."); 00177 return true; 00178 }