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.hasFeature(Sparc::FeatureV9)) != 0; 39 } 40 41 void SparcInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const { 42 OS << '%' << getRegisterName(Reg); 43 } 44 45 void SparcInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg, 46 unsigned AltIdx) const { 47 OS << '%' << getRegisterName(Reg, AltIdx); 48 } 49 50 void SparcInstPrinter::printInst(const MCInst *MI, uint64_t Address, 51 StringRef Annot, const MCSubtargetInfo &STI, 52 raw_ostream &O) { 53 if (!printAliasInstr(MI, Address, STI, O) && 54 !printSparcAliasInstr(MI, STI, O)) 55 printInstruction(MI, Address, STI, O); 56 printAnnotation(O, Annot); 57 } 58 59 bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI, 60 const MCSubtargetInfo &STI, 61 raw_ostream &O) { 62 switch (MI->getOpcode()) { 63 default: return false; 64 case SP::JMPLrr: 65 case SP::JMPLri: { 66 if (MI->getNumOperands() != 3) 67 return false; 68 if (!MI->getOperand(0).isReg()) 69 return false; 70 switch (MI->getOperand(0).getReg()) { 71 default: return false; 72 case SP::G0: // jmp $addr | ret | retl 73 if (MI->getOperand(2).isImm() && 74 MI->getOperand(2).getImm() == 8) { 75 switch(MI->getOperand(1).getReg()) { 76 default: break; 77 case SP::I7: O << "\tret"; return true; 78 case SP::O7: O << "\tretl"; return true; 79 } 80 } 81 O << "\tjmp "; printMemOperand(MI, 1, STI, O); 82 return true; 83 case SP::O7: // call $addr 84 O << "\tcall "; printMemOperand(MI, 1, STI, O); 85 return true; 86 } 87 } 88 case SP::V9FCMPS: case SP::V9FCMPD: case SP::V9FCMPQ: 89 case SP::V9FCMPES: case SP::V9FCMPED: case SP::V9FCMPEQ: { 90 if (isV9(STI) 91 || (MI->getNumOperands() != 3) 92 || (!MI->getOperand(0).isReg()) 93 || (MI->getOperand(0).getReg() != SP::FCC0)) 94 return false; 95 // if V8, skip printing %fcc0. 96 switch(MI->getOpcode()) { 97 default: 98 case SP::V9FCMPS: O << "\tfcmps "; break; 99 case SP::V9FCMPD: O << "\tfcmpd "; break; 100 case SP::V9FCMPQ: O << "\tfcmpq "; break; 101 case SP::V9FCMPES: O << "\tfcmpes "; break; 102 case SP::V9FCMPED: O << "\tfcmped "; break; 103 case SP::V9FCMPEQ: O << "\tfcmpeq "; break; 104 } 105 printOperand(MI, 1, STI, O); 106 O << ", "; 107 printOperand(MI, 2, STI, O); 108 return true; 109 } 110 } 111 } 112 113 void SparcInstPrinter::printOperand(const MCInst *MI, int opNum, 114 const MCSubtargetInfo &STI, 115 raw_ostream &O) { 116 const MCOperand &MO = MI->getOperand (opNum); 117 118 if (MO.isReg()) { 119 unsigned Reg = MO.getReg(); 120 if (isV9(STI)) 121 printRegName(O, Reg, SP::RegNamesStateReg); 122 else 123 printRegName(O, Reg); 124 return ; 125 } 126 127 if (MO.isImm()) { 128 switch (MI->getOpcode()) { 129 default: 130 O << (int)MO.getImm(); 131 return; 132 133 case SP::TICCri: // Fall through 134 case SP::TICCrr: // Fall through 135 case SP::TRAPri: // Fall through 136 case SP::TRAPrr: // Fall through 137 case SP::TXCCri: // Fall through 138 case SP::TXCCrr: // Fall through 139 // Only seven-bit values up to 127. 140 O << ((int) MO.getImm() & 0x7f); 141 return; 142 } 143 } 144 145 assert(MO.isExpr() && "Unknown operand kind in printOperand"); 146 MO.getExpr()->print(O, &MAI); 147 } 148 149 void SparcInstPrinter::printMemOperand(const MCInst *MI, int opNum, 150 const MCSubtargetInfo &STI, 151 raw_ostream &O) { 152 const MCOperand &Op1 = MI->getOperand(opNum); 153 const MCOperand &Op2 = MI->getOperand(opNum + 1); 154 155 bool PrintedFirstOperand = false; 156 if (Op1.isReg() && Op1.getReg() != SP::G0) { 157 printOperand(MI, opNum, STI, O); 158 PrintedFirstOperand = true; 159 } 160 161 // Skip the second operand iff it adds nothing (literal 0 or %g0) and we've 162 // already printed the first one 163 const bool SkipSecondOperand = 164 PrintedFirstOperand && ((Op2.isReg() && Op2.getReg() == SP::G0) || 165 (Op2.isImm() && Op2.getImm() == 0)); 166 167 if (!SkipSecondOperand) { 168 if (PrintedFirstOperand) 169 O << '+'; 170 printOperand(MI, opNum + 1, STI, O); 171 } 172 } 173 174 void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum, 175 const MCSubtargetInfo &STI, 176 raw_ostream &O) { 177 int CC = (int)MI->getOperand(opNum).getImm(); 178 switch (MI->getOpcode()) { 179 default: break; 180 case SP::FBCOND: 181 case SP::FBCONDA: 182 case SP::FBCOND_V9: 183 case SP::FBCONDA_V9: 184 case SP::BPFCC: 185 case SP::BPFCCA: 186 case SP::BPFCCNT: 187 case SP::BPFCCANT: 188 case SP::MOVFCCrr: case SP::V9MOVFCCrr: 189 case SP::MOVFCCri: case SP::V9MOVFCCri: 190 case SP::FMOVS_FCC: case SP::V9FMOVS_FCC: 191 case SP::FMOVD_FCC: case SP::V9FMOVD_FCC: 192 case SP::FMOVQ_FCC: case SP::V9FMOVQ_FCC: 193 // Make sure CC is a fp conditional flag. 194 CC = (CC < SPCC::FCC_BEGIN) ? (CC + SPCC::FCC_BEGIN) : CC; 195 break; 196 case SP::CBCOND: 197 case SP::CBCONDA: 198 // Make sure CC is a cp conditional flag. 199 CC = (CC < SPCC::CPCC_BEGIN) ? (CC + SPCC::CPCC_BEGIN) : CC; 200 break; 201 case SP::BPR: 202 case SP::BPRA: 203 case SP::BPRNT: 204 case SP::BPRANT: 205 case SP::MOVRri: 206 case SP::MOVRrr: 207 case SP::FMOVRS: 208 case SP::FMOVRD: 209 case SP::FMOVRQ: 210 // Make sure CC is a register conditional flag. 211 CC = (CC < SPCC::REG_BEGIN) ? (CC + SPCC::REG_BEGIN) : CC; 212 break; 213 } 214 O << SPARCCondCodeToString((SPCC::CondCodes)CC); 215 } 216 217 bool SparcInstPrinter::printGetPCX(const MCInst *MI, unsigned opNum, 218 const MCSubtargetInfo &STI, 219 raw_ostream &O) { 220 llvm_unreachable("FIXME: Implement SparcInstPrinter::printGetPCX."); 221 return true; 222 } 223 224 void SparcInstPrinter::printMembarTag(const MCInst *MI, int opNum, 225 const MCSubtargetInfo &STI, 226 raw_ostream &O) { 227 static const char *const TagNames[] = { 228 "#LoadLoad", "#StoreLoad", "#LoadStore", "#StoreStore", 229 "#Lookaside", "#MemIssue", "#Sync"}; 230 231 unsigned Imm = MI->getOperand(opNum).getImm(); 232 233 if (Imm > 127) { 234 O << Imm; 235 return; 236 } 237 238 bool First = true; 239 for (unsigned i = 0; i < std::size(TagNames); i++) { 240 if (Imm & (1 << i)) { 241 O << (First ? "" : " | ") << TagNames[i]; 242 First = false; 243 } 244 } 245 } 246 247 void SparcInstPrinter::printASITag(const MCInst *MI, int opNum, 248 const MCSubtargetInfo &STI, raw_ostream &O) { 249 unsigned Imm = MI->getOperand(opNum).getImm(); 250 auto ASITag = SparcASITag::lookupASITagByEncoding(Imm); 251 if (isV9(STI) && ASITag) 252 O << '#' << ASITag->Name; 253 else 254 O << Imm; 255 } 256 257 void SparcInstPrinter::printPrefetchTag(const MCInst *MI, int opNum, 258 const MCSubtargetInfo &STI, 259 raw_ostream &O) { 260 unsigned Imm = MI->getOperand(opNum).getImm(); 261 auto PrefetchTag = SparcPrefetchTag::lookupPrefetchTagByEncoding(Imm); 262 if (PrefetchTag) 263 O << '#' << PrefetchTag->Name; 264 else 265 O << Imm; 266 } 267