Path: blob/main/contrib/llvm-project/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.cpp
35294 views
//===- ARCInstPrinter.cpp - ARC MCInst to assembly syntax -------*- C++ -*-===//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 ARC MCInst to a .s file.9//10//===----------------------------------------------------------------------===//1112#include "ARCInstPrinter.h"13#include "MCTargetDesc/ARCInfo.h"14#include "llvm/ADT/StringExtras.h"15#include "llvm/MC/MCExpr.h"16#include "llvm/MC/MCInst.h"17#include "llvm/MC/MCInstrInfo.h"18#include "llvm/MC/MCSymbol.h"19#include "llvm/Support/Casting.h"20#include "llvm/Support/Debug.h"21#include "llvm/Support/raw_ostream.h"2223using namespace llvm;2425#define DEBUG_TYPE "asm-printer"2627#include "ARCGenAsmWriter.inc"2829template <class T>30static const char *BadConditionCode(T cc) {31LLVM_DEBUG(dbgs() << "Unknown condition code passed: " << cc << "\n");32return "{unknown-cc}";33}3435static const char *ARCBRCondCodeToString(ARCCC::BRCondCode BRCC) {36switch (BRCC) {37case ARCCC::BREQ:38return "eq";39case ARCCC::BRNE:40return "ne";41case ARCCC::BRLT:42return "lt";43case ARCCC::BRGE:44return "ge";45case ARCCC::BRLO:46return "lo";47case ARCCC::BRHS:48return "hs";49}50return BadConditionCode(BRCC);51}5253static const char *ARCCondCodeToString(ARCCC::CondCode CC) {54switch (CC) {55case ARCCC::EQ:56return "eq";57case ARCCC::NE:58return "ne";59case ARCCC::P:60return "p";61case ARCCC::N:62return "n";63case ARCCC::HS:64return "hs";65case ARCCC::LO:66return "lo";67case ARCCC::GT:68return "gt";69case ARCCC::GE:70return "ge";71case ARCCC::VS:72return "vs";73case ARCCC::VC:74return "vc";75case ARCCC::LT:76return "lt";77case ARCCC::LE:78return "le";79case ARCCC::HI:80return "hi";81case ARCCC::LS:82return "ls";83case ARCCC::PNZ:84return "pnz";85case ARCCC::AL:86return "al";87case ARCCC::NZ:88return "nz";89case ARCCC::Z:90return "z";91}92return BadConditionCode(CC);93}9495void ARCInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const {96OS << StringRef(getRegisterName(Reg)).lower();97}9899void ARCInstPrinter::printInst(const MCInst *MI, uint64_t Address,100StringRef Annot, const MCSubtargetInfo &STI,101raw_ostream &O) {102printInstruction(MI, Address, O);103printAnnotation(O, Annot);104}105106static void printExpr(const MCExpr *Expr, const MCAsmInfo *MAI,107raw_ostream &OS) {108int Offset = 0;109const MCSymbolRefExpr *SRE;110111if (const auto *CE = dyn_cast<MCConstantExpr>(Expr)) {112OS << "0x";113OS.write_hex(CE->getValue());114return;115}116117if (const auto *BE = dyn_cast<MCBinaryExpr>(Expr)) {118SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());119const auto *CE = dyn_cast<MCConstantExpr>(BE->getRHS());120assert(SRE && CE && "Binary expression must be sym+const.");121Offset = CE->getValue();122} else {123SRE = dyn_cast<MCSymbolRefExpr>(Expr);124assert(SRE && "Unexpected MCExpr type.");125}126assert(SRE->getKind() == MCSymbolRefExpr::VK_None);127128// Symbols are prefixed with '@'129OS << '@';130SRE->getSymbol().print(OS, MAI);131132if (Offset) {133if (Offset > 0)134OS << '+';135OS << Offset;136}137}138139void ARCInstPrinter::printOperand(const MCInst *MI, unsigned OpNum,140raw_ostream &O) {141const MCOperand &Op = MI->getOperand(OpNum);142if (Op.isReg()) {143printRegName(O, Op.getReg());144return;145}146147if (Op.isImm()) {148O << Op.getImm();149return;150}151152assert(Op.isExpr() && "unknown operand kind in printOperand");153printExpr(Op.getExpr(), &MAI, O);154}155156void ARCInstPrinter::printMemOperandRI(const MCInst *MI, unsigned OpNum,157raw_ostream &O) {158const MCOperand &base = MI->getOperand(OpNum);159const MCOperand &offset = MI->getOperand(OpNum + 1);160assert(base.isReg() && "Base should be register.");161assert(offset.isImm() && "Offset should be immediate.");162printRegName(O, base.getReg());163O << "," << offset.getImm();164}165166void ARCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,167raw_ostream &O) {168169const MCOperand &Op = MI->getOperand(OpNum);170assert(Op.isImm() && "Predicate operand is immediate.");171O << ARCCondCodeToString((ARCCC::CondCode)Op.getImm());172}173174void ARCInstPrinter::printBRCCPredicateOperand(const MCInst *MI, unsigned OpNum,175raw_ostream &O) {176const MCOperand &Op = MI->getOperand(OpNum);177assert(Op.isImm() && "Predicate operand is immediate.");178O << ARCBRCondCodeToString((ARCCC::BRCondCode)Op.getImm());179}180181void ARCInstPrinter::printCCOperand(const MCInst *MI, int OpNum,182raw_ostream &O) {183O << ARCCondCodeToString((ARCCC::CondCode)MI->getOperand(OpNum).getImm());184}185186void ARCInstPrinter::printU6ShiftedBy(unsigned ShiftBy, const MCInst *MI,187int OpNum, raw_ostream &O) {188const MCOperand &MO = MI->getOperand(OpNum);189if (MO.isImm()) {190unsigned Value = MO.getImm();191unsigned Value2 = Value >> ShiftBy;192if (Value2 > 0x3F || (Value2 << ShiftBy != Value)) {193errs() << "!!! Instruction has out-of-range U6 immediate operand:\n"194<< " Opcode is " << MI->getOpcode() << "; operand value is "195<< Value;196if (ShiftBy)197errs() << " scaled by " << (1 << ShiftBy) << "\n";198assert(false && "instruction has wrong format");199}200}201printOperand(MI, OpNum, O);202}203204void ARCInstPrinter::printU6(const MCInst *MI, int OpNum, raw_ostream &O) {205printU6ShiftedBy(0, MI, OpNum, O);206}207208209