brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.0 KiB · 2d1a4fe Raw
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