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 17 #include "Sparc.h" 18 #include "llvm/MC/MCExpr.h" 19 #include "llvm/MC/MCInst.h" 20 #include "llvm/MC/MCSymbol.h" 21 #include "llvm/Support/raw_ostream.h" 22 using namespace llvm; 23 24 #define GET_INSTRUCTION_NAME 25 #define PRINT_ALIAS_INSTR 26 #include "SparcGenAsmWriter.inc" 27 28 void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const 29 { 30 OS << '%' << StringRef(getRegisterName(RegNo)).lower(); 31 } 32 33 void SparcInstPrinter::printInst(const MCInst *MI, raw_ostream &O, 34 StringRef Annot) 35 { 36 if (!printAliasInstr(MI, O) && !printSparcAliasInstr(MI, O)) 37 printInstruction(MI, O); 38 printAnnotation(O, Annot); 39 } 40 41 bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI, raw_ostream &O) 42 { 43 switch (MI->getOpcode()) { 44 default: return false; 45 case SP::JMPLrr: 46 case SP::JMPLri: { 47 if (MI->getNumOperands() != 3) 48 return false; 49 if (!MI->getOperand(0).isReg()) 50 return false; 51 switch (MI->getOperand(0).getReg()) { 52 default: return false; 53 case SP::G0: // jmp $addr 54 O << "\tjmp "; printMemOperand(MI, 1, O); 55 return true; 56 case SP::O7: // call $addr 57 O << "\tcall "; printMemOperand(MI, 1, O); 58 return true; 59 } 60 } 61 } 62 } 63 64 void SparcInstPrinter::printOperand(const MCInst *MI, int opNum, 65 raw_ostream &O) 66 { 67 const MCOperand &MO = MI->getOperand (opNum); 68 69 if (MO.isReg()) { 70 printRegName(O, MO.getReg()); 71 return ; 72 } 73 74 if (MO.isImm()) { 75 O << (int)MO.getImm(); 76 return; 77 } 78 79 assert(MO.isExpr() && "Unknown operand kind in printOperand"); 80 MO.getExpr()->print(O); 81 } 82 83 void SparcInstPrinter::printMemOperand(const MCInst *MI, int opNum, 84 raw_ostream &O, const char *Modifier) 85 { 86 printOperand(MI, opNum, O); 87 88 // If this is an ADD operand, emit it like normal operands. 89 if (Modifier && !strcmp(Modifier, "arith")) { 90 O << ", "; 91 printOperand(MI, opNum+1, O); 92 return; 93 } 94 const MCOperand &MO = MI->getOperand(opNum+1); 95 96 if (MO.isReg() && MO.getReg() == SP::G0) 97 return; // don't print "+%g0" 98 if (MO.isImm() && MO.getImm() == 0) 99 return; // don't print "+0" 100 101 O << "+"; 102 103 printOperand(MI, opNum+1, O); 104 } 105 106 void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum, 107 raw_ostream &O) 108 { 109 int CC = (int)MI->getOperand(opNum).getImm(); 110 switch (MI->getOpcode()) { 111 default: break; 112 case SP::FBCOND: 113 case SP::MOVFCCrr: 114 case SP::MOVFCCri: 115 case SP::FMOVS_FCC: 116 case SP::FMOVD_FCC: 117 case SP::FMOVQ_FCC: // Make sure CC is a fp conditional flag. 118 CC = (CC < 16) ? (CC + 16) : CC; 119 break; 120 } 121 O << SPARCCondCodeToString((SPCC::CondCodes)CC); 122 } 123 124 bool SparcInstPrinter::printGetPCX(const MCInst *MI, unsigned opNum, 125 raw_ostream &O) 126 { 127 assert(0 && "FIXME: Implement SparcInstPrinter::printGetPCX."); 128 return true; 129 } 130