1 //===-- SparcInstPrinter.cpp - Convert Sparc MCInst to assembly syntax -----==// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This class prints an Sparc MCInst to a .s file. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "SparcInstPrinter.h" 14 #include "Sparc.h" 15 #include "llvm/MC/MCExpr.h" 16 #include "llvm/MC/MCInst.h" 17 #include "llvm/MC/MCRegisterInfo.h" 18 #include "llvm/MC/MCSubtargetInfo.h" 19 #include "llvm/MC/MCSymbol.h" 20 #include "llvm/Support/raw_ostream.h" 21 using namespace llvm; 22 23 #define DEBUG_TYPE "asm-printer" 24 25 // The generated AsmMatcher SparcGenAsmWriter uses "Sparc" as the target 26 // namespace. But SPARC backend uses "SP" as its namespace. 27 namespace llvm { 28 namespace Sparc { 29 using namespace SP; 30 } 31 } 32 33 #define GET_INSTRUCTION_NAME 34 #define PRINT_ALIAS_INSTR 35 #include "SparcGenAsmWriter.inc" 36 37 bool SparcInstPrinter::isV9(const MCSubtargetInfo &STI) const { 38 return (STI.getFeatureBits()[Sparc::FeatureV9]) != 0; 39 } 40 41 void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const 42 { 43 OS << '%' << StringRef(getRegisterName(RegNo)).lower(); 44 } 45 46 void SparcInstPrinter::printInst(const MCInst *MI, uint64_t Address, 47 StringRef Annot, const MCSubtargetInfo &STI, 48 raw_ostream &O) { 49 if (!printAliasInstr(MI, Address, STI, O) && 50 !printSparcAliasInstr(MI, STI, O)) 51 printInstruction(MI, Address, STI, O); 52 printAnnotation(O, Annot); 53 } 54 55 bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI, 56 const MCSubtargetInfo &STI, 57 raw_ostream &O) { 58 switch (MI->getOpcode()) { 59 default: return false; 60 case SP::JMPLrr: 61 case SP::JMPLri: { 62 if (MI->getNumOperands() != 3) 63 return false; 64 if (!MI->getOperand(0).isReg()) 65 return false; 66 switch (MI->getOperand(0).getReg()) { 67 default: return false; 68 case SP::G0: // jmp $addr | ret | retl 69 if (MI->getOperand(2).isImm() && 70 MI->getOperand(2).getImm() == 8) { 71 switch(MI->getOperand(1).getReg()) { 72 default: break; 73 case SP::I7: O << "\tret"; return true; 74 case SP::O7: O << "\tretl"; return true; 75 } 76 } 77 O << "\tjmp "; printMemOperand(MI, 1, STI, O); 78 return true; 79 case SP::O7: // call $addr 80 O << "\tcall "; printMemOperand(MI, 1, STI, O); 81 return true; 82 } 83 } 84 case SP::V9FCMPS: case SP::V9FCMPD: case SP::V9FCMPQ: 85 case SP::V9FCMPES: case SP::V9FCMPED: case SP::V9FCMPEQ: { 86 if (isV9(STI) 87 || (MI->getNumOperands() != 3) 88 || (!MI->getOperand(0).isReg()) 89 || (MI->getOperand(0).getReg() != SP::FCC0)) 90 return false; 91 // if V8, skip printing %fcc0. 92 switch(MI->getOpcode()) { 93 default: 94 case SP::V9FCMPS: O << "\tfcmps "; break; 95 case SP::V9FCMPD: O << "\tfcmpd "; break; 96 case SP::V9FCMPQ: O << "\tfcmpq "; break; 97 case SP::V9FCMPES: O << "\tfcmpes "; break; 98 case SP::V9FCMPED: O << "\tfcmped "; break; 99 case SP::V9FCMPEQ: O << "\tfcmpeq "; break; 100 } 101 printOperand(MI, 1, STI, O); 102 O << ", "; 103 printOperand(MI, 2, STI, O); 104 return true; 105 } 106 } 107 } 108 109 void SparcInstPrinter::printOperand(const MCInst *MI, int opNum, 110 const MCSubtargetInfo &STI, 111 raw_ostream &O) { 112 const MCOperand &MO = MI->getOperand (opNum); 113 114 if (MO.isReg()) { 115 printRegName(O, MO.getReg()); 116 return ; 117 } 118 119 if (MO.isImm()) { 120 switch (MI->getOpcode()) { 121 default: 122 O << (int)MO.getImm(); 123 return; 124 125 case SP::TICCri: // Fall through 126 case SP::TICCrr: // Fall through 127 case SP::TRAPri: // Fall through 128 case SP::TRAPrr: // Fall through 129 case SP::TXCCri: // Fall through 130 case SP::TXCCrr: // Fall through 131 // Only seven-bit values up to 127. 132 O << ((int) MO.getImm() & 0x7f); 133 return; 134 } 135 } 136 137 assert(MO.isExpr() && "Unknown operand kind in printOperand"); 138 MO.getExpr()->print(O, &MAI); 139 } 140 141 void SparcInstPrinter::printMemOperand(const MCInst *MI, int opNum, 142 const MCSubtargetInfo &STI, 143 raw_ostream &O, const char *Modifier) { 144 printOperand(MI, opNum, STI, O); 145 146 // If this is an ADD operand, emit it like normal operands. 147 if (Modifier && !strcmp(Modifier, "arith")) { 148 O << ", "; 149 printOperand(MI, opNum+1, STI, O); 150 return; 151 } 152 const MCOperand &MO = MI->getOperand(opNum+1); 153 154 if (MO.isReg() && MO.getReg() == SP::G0) 155 return; // don't print "+%g0" 156 if (MO.isImm() && MO.getImm() == 0) 157 return; // don't print "+0" 158 159 O << "+"; 160 161 printOperand(MI, opNum+1, STI, O); 162 } 163 164 void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum, 165 const MCSubtargetInfo &STI, 166 raw_ostream &O) { 167 int CC = (int)MI->getOperand(opNum).getImm(); 168 switch (MI->getOpcode()) { 169 default: break; 170 case SP::FBCOND: 171 case SP::FBCONDA: 172 case SP::BPFCC: 173 case SP::BPFCCA: 174 case SP::BPFCCNT: 175 case SP::BPFCCANT: 176 case SP::MOVFCCrr: case SP::V9MOVFCCrr: 177 case SP::MOVFCCri: case SP::V9MOVFCCri: 178 case SP::FMOVS_FCC: case SP::V9FMOVS_FCC: 179 case SP::FMOVD_FCC: case SP::V9FMOVD_FCC: 180 case SP::FMOVQ_FCC: case SP::V9FMOVQ_FCC: 181 // Make sure CC is a fp conditional flag. 182 CC = (CC < 16) ? (CC + 16) : CC; 183 break; 184 case SP::CBCOND: 185 case SP::CBCONDA: 186 // Make sure CC is a cp conditional flag. 187 CC = (CC < 32) ? (CC + 32) : CC; 188 break; 189 } 190 O << SPARCCondCodeToString((SPCC::CondCodes)CC); 191 } 192 193 bool SparcInstPrinter::printGetPCX(const MCInst *MI, unsigned opNum, 194 const MCSubtargetInfo &STI, 195 raw_ostream &O) { 196 llvm_unreachable("FIXME: Implement SparcInstPrinter::printGetPCX."); 197 return true; 198 } 199 200 void SparcInstPrinter::printMembarTag(const MCInst *MI, int opNum, 201 const MCSubtargetInfo &STI, 202 raw_ostream &O) { 203 static const char *const TagNames[] = { 204 "#LoadLoad", "#StoreLoad", "#LoadStore", "#StoreStore", 205 "#Lookaside", "#MemIssue", "#Sync"}; 206 207 unsigned Imm = MI->getOperand(opNum).getImm(); 208 209 if (Imm > 127) { 210 O << Imm; 211 return; 212 } 213 214 bool First = true; 215 for (unsigned i = 0; i < sizeof(TagNames) / sizeof(char *); i++) { 216 if (Imm & (1 << i)) { 217 O << (First ? "" : " | ") << TagNames[i]; 218 First = false; 219 } 220 } 221 } 222