294 lines · cpp
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-exception6//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/MCAsmInfo.h"16#include "llvm/MC/MCExpr.h"17#include "llvm/MC/MCInst.h"18#include "llvm/MC/MCSubtargetInfo.h"19#include "llvm/MC/MCSymbol.h"20#include "llvm/Support/raw_ostream.h"21using namespace llvm;22 23#define DEBUG_TYPE "asm-printer"24 25// The generated AsmMatcher SparcGenAsmWriter uses "Sparc" as the target26// namespace. But SPARC backend uses "SP" as its namespace.27namespace llvm {28namespace Sparc {29 using namespace SP;30}31}32 33#define GET_INSTRUCTION_NAME34#define PRINT_ALIAS_INSTR35#include "SparcGenAsmWriter.inc"36 37bool SparcInstPrinter::isV9(const MCSubtargetInfo &STI) const {38 return (STI.hasFeature(Sparc::FeatureV9)) != 0;39}40 41void SparcInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {42 OS << '%' << getRegisterName(Reg);43}44 45void SparcInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg,46 unsigned AltIdx) const {47 OS << '%' << getRegisterName(Reg, AltIdx);48}49 50void 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 59bool 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().id()) {71 default: return false;72 case SP::G0: // jmp $addr | ret | retl73 if (MI->getOperand(2).isImm() &&74 MI->getOperand(2).getImm() == 8) {75 switch (MI->getOperand(1).getReg().id()) {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 $addr84 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 113void 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 MCRegister Reg = MO.getReg();120 if (isV9(STI))121 printRegName(O, Reg, SP::RegNamesStateReg);122 else123 printRegName(O, Reg);124 return ;125 }126 127 if (MO.isImm()) {128 switch (MI->getOpcode()) {129 default:130 markup(O, Markup::Immediate) << formatImm(int32_t(MO.getImm()));131 return;132 133 case SP::TICCri: // Fall through134 case SP::TICCrr: // Fall through135 case SP::TRAPri: // Fall through136 case SP::TRAPrr: // Fall through137 case SP::TXCCri: // Fall through138 case SP::TXCCrr: // Fall through139 // 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 MAI.printExpr(O, *MO.getExpr());147}148 149void 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've162 // already printed the first one163 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 174void 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::CPBCOND:197 case SP::CPBCONDA: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 217bool 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 224void 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 247void 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 else254 O << Imm;255}256 257void 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 else265 O << Imm;266}267 268void SparcInstPrinter::printCTILabel(const MCInst *MI, uint64_t Address,269 unsigned OpNum, const MCSubtargetInfo &STI,270 raw_ostream &O) {271 const MCOperand &Op = MI->getOperand(OpNum);272 273 // If the label has already been resolved to an immediate offset (say, when274 // we're running the disassembler), just print the immediate.275 if (Op.isImm()) {276 int64_t Offset = Op.getImm();277 if (PrintBranchImmAsAddress) {278 uint64_t Target = Address + Offset;279 if (STI.getTargetTriple().isSPARC32())280 Target &= 0xffffffff;281 O << formatHex(Target);282 } else {283 O << ".";284 if (Offset >= 0)285 O << "+";286 O << Offset;287 }288 return;289 }290 291 // Otherwise, just print the expression.292 MAI.printExpr(O, *Op.getExpr());293}294