Path: blob/main/contrib/llvm-project/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
35294 views
//===-- SparcInstPrinter.cpp - Convert Sparc MCInst to assembly syntax -----==//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This class prints an Sparc MCInst to a .s file.9//10//===----------------------------------------------------------------------===//1112#include "SparcInstPrinter.h"13#include "Sparc.h"14#include "llvm/MC/MCExpr.h"15#include "llvm/MC/MCInst.h"16#include "llvm/MC/MCRegisterInfo.h"17#include "llvm/MC/MCSubtargetInfo.h"18#include "llvm/MC/MCSymbol.h"19#include "llvm/Support/raw_ostream.h"20using namespace llvm;2122#define DEBUG_TYPE "asm-printer"2324// The generated AsmMatcher SparcGenAsmWriter uses "Sparc" as the target25// namespace. But SPARC backend uses "SP" as its namespace.26namespace llvm {27namespace Sparc {28using namespace SP;29}30}3132#define GET_INSTRUCTION_NAME33#define PRINT_ALIAS_INSTR34#include "SparcGenAsmWriter.inc"3536bool SparcInstPrinter::isV9(const MCSubtargetInfo &STI) const {37return (STI.hasFeature(Sparc::FeatureV9)) != 0;38}3940void SparcInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const {41OS << '%' << getRegisterName(Reg);42}4344void SparcInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg,45unsigned AltIdx) const {46OS << '%' << getRegisterName(Reg, AltIdx);47}4849void SparcInstPrinter::printInst(const MCInst *MI, uint64_t Address,50StringRef Annot, const MCSubtargetInfo &STI,51raw_ostream &O) {52if (!printAliasInstr(MI, Address, STI, O) &&53!printSparcAliasInstr(MI, STI, O))54printInstruction(MI, Address, STI, O);55printAnnotation(O, Annot);56}5758bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI,59const MCSubtargetInfo &STI,60raw_ostream &O) {61switch (MI->getOpcode()) {62default: return false;63case SP::JMPLrr:64case SP::JMPLri: {65if (MI->getNumOperands() != 3)66return false;67if (!MI->getOperand(0).isReg())68return false;69switch (MI->getOperand(0).getReg()) {70default: return false;71case SP::G0: // jmp $addr | ret | retl72if (MI->getOperand(2).isImm() &&73MI->getOperand(2).getImm() == 8) {74switch(MI->getOperand(1).getReg()) {75default: break;76case SP::I7: O << "\tret"; return true;77case SP::O7: O << "\tretl"; return true;78}79}80O << "\tjmp "; printMemOperand(MI, 1, STI, O);81return true;82case SP::O7: // call $addr83O << "\tcall "; printMemOperand(MI, 1, STI, O);84return true;85}86}87case SP::V9FCMPS: case SP::V9FCMPD: case SP::V9FCMPQ:88case SP::V9FCMPES: case SP::V9FCMPED: case SP::V9FCMPEQ: {89if (isV9(STI)90|| (MI->getNumOperands() != 3)91|| (!MI->getOperand(0).isReg())92|| (MI->getOperand(0).getReg() != SP::FCC0))93return false;94// if V8, skip printing %fcc0.95switch(MI->getOpcode()) {96default:97case SP::V9FCMPS: O << "\tfcmps "; break;98case SP::V9FCMPD: O << "\tfcmpd "; break;99case SP::V9FCMPQ: O << "\tfcmpq "; break;100case SP::V9FCMPES: O << "\tfcmpes "; break;101case SP::V9FCMPED: O << "\tfcmped "; break;102case SP::V9FCMPEQ: O << "\tfcmpeq "; break;103}104printOperand(MI, 1, STI, O);105O << ", ";106printOperand(MI, 2, STI, O);107return true;108}109}110}111112void SparcInstPrinter::printOperand(const MCInst *MI, int opNum,113const MCSubtargetInfo &STI,114raw_ostream &O) {115const MCOperand &MO = MI->getOperand (opNum);116117if (MO.isReg()) {118unsigned Reg = MO.getReg();119if (isV9(STI))120printRegName(O, Reg, SP::RegNamesStateReg);121else122printRegName(O, Reg);123return ;124}125126if (MO.isImm()) {127switch (MI->getOpcode()) {128default:129O << (int)MO.getImm();130return;131132case SP::TICCri: // Fall through133case SP::TICCrr: // Fall through134case SP::TRAPri: // Fall through135case SP::TRAPrr: // Fall through136case SP::TXCCri: // Fall through137case SP::TXCCrr: // Fall through138// Only seven-bit values up to 127.139O << ((int) MO.getImm() & 0x7f);140return;141}142}143144assert(MO.isExpr() && "Unknown operand kind in printOperand");145MO.getExpr()->print(O, &MAI);146}147148void SparcInstPrinter::printMemOperand(const MCInst *MI, int opNum,149const MCSubtargetInfo &STI,150raw_ostream &O) {151const MCOperand &Op1 = MI->getOperand(opNum);152const MCOperand &Op2 = MI->getOperand(opNum + 1);153154bool PrintedFirstOperand = false;155if (Op1.isReg() && Op1.getReg() != SP::G0) {156printOperand(MI, opNum, STI, O);157PrintedFirstOperand = true;158}159160// Skip the second operand iff it adds nothing (literal 0 or %g0) and we've161// already printed the first one162const bool SkipSecondOperand =163PrintedFirstOperand && ((Op2.isReg() && Op2.getReg() == SP::G0) ||164(Op2.isImm() && Op2.getImm() == 0));165166if (!SkipSecondOperand) {167if (PrintedFirstOperand)168O << '+';169printOperand(MI, opNum + 1, STI, O);170}171}172173void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum,174const MCSubtargetInfo &STI,175raw_ostream &O) {176int CC = (int)MI->getOperand(opNum).getImm();177switch (MI->getOpcode()) {178default: break;179case SP::FBCOND:180case SP::FBCONDA:181case SP::FBCOND_V9:182case SP::FBCONDA_V9:183case SP::BPFCC:184case SP::BPFCCA:185case SP::BPFCCNT:186case SP::BPFCCANT:187case SP::MOVFCCrr: case SP::V9MOVFCCrr:188case SP::MOVFCCri: case SP::V9MOVFCCri:189case SP::FMOVS_FCC: case SP::V9FMOVS_FCC:190case SP::FMOVD_FCC: case SP::V9FMOVD_FCC:191case SP::FMOVQ_FCC: case SP::V9FMOVQ_FCC:192// Make sure CC is a fp conditional flag.193CC = (CC < SPCC::FCC_BEGIN) ? (CC + SPCC::FCC_BEGIN) : CC;194break;195case SP::CBCOND:196case SP::CBCONDA:197// Make sure CC is a cp conditional flag.198CC = (CC < SPCC::CPCC_BEGIN) ? (CC + SPCC::CPCC_BEGIN) : CC;199break;200case SP::BPR:201case SP::BPRA:202case SP::BPRNT:203case SP::BPRANT:204case SP::MOVRri:205case SP::MOVRrr:206case SP::FMOVRS:207case SP::FMOVRD:208case SP::FMOVRQ:209// Make sure CC is a register conditional flag.210CC = (CC < SPCC::REG_BEGIN) ? (CC + SPCC::REG_BEGIN) : CC;211break;212}213O << SPARCCondCodeToString((SPCC::CondCodes)CC);214}215216bool SparcInstPrinter::printGetPCX(const MCInst *MI, unsigned opNum,217const MCSubtargetInfo &STI,218raw_ostream &O) {219llvm_unreachable("FIXME: Implement SparcInstPrinter::printGetPCX.");220return true;221}222223void SparcInstPrinter::printMembarTag(const MCInst *MI, int opNum,224const MCSubtargetInfo &STI,225raw_ostream &O) {226static const char *const TagNames[] = {227"#LoadLoad", "#StoreLoad", "#LoadStore", "#StoreStore",228"#Lookaside", "#MemIssue", "#Sync"};229230unsigned Imm = MI->getOperand(opNum).getImm();231232if (Imm > 127) {233O << Imm;234return;235}236237bool First = true;238for (unsigned i = 0; i < std::size(TagNames); i++) {239if (Imm & (1 << i)) {240O << (First ? "" : " | ") << TagNames[i];241First = false;242}243}244}245246void SparcInstPrinter::printASITag(const MCInst *MI, int opNum,247const MCSubtargetInfo &STI, raw_ostream &O) {248unsigned Imm = MI->getOperand(opNum).getImm();249auto ASITag = SparcASITag::lookupASITagByEncoding(Imm);250if (isV9(STI) && ASITag)251O << '#' << ASITag->Name;252else253O << Imm;254}255256void SparcInstPrinter::printPrefetchTag(const MCInst *MI, int opNum,257const MCSubtargetInfo &STI,258raw_ostream &O) {259unsigned Imm = MI->getOperand(opNum).getImm();260auto PrefetchTag = SparcPrefetchTag::lookupPrefetchTagByEncoding(Imm);261if (PrefetchTag)262O << '#' << PrefetchTag->Name;263else264O << Imm;265}266267268