Path: blob/main/contrib/llvm-project/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
35293 views
//===- ARCDisassembler.cpp - Disassembler for ARC ---------------*- 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/// \file9/// This file is part of the ARC Disassembler.10///11//===----------------------------------------------------------------------===//1213#include "ARC.h"14#include "ARCRegisterInfo.h"15#include "MCTargetDesc/ARCMCTargetDesc.h"16#include "TargetInfo/ARCTargetInfo.h"17#include "llvm/MC/MCContext.h"18#include "llvm/MC/MCDecoderOps.h"19#include "llvm/MC/MCDisassembler/MCDisassembler.h"20#include "llvm/MC/MCInst.h"21#include "llvm/MC/MCInstrInfo.h"22#include "llvm/MC/MCSubtargetInfo.h"23#include "llvm/MC/TargetRegistry.h"2425using namespace llvm;2627#define DEBUG_TYPE "arc-disassembler"2829using DecodeStatus = MCDisassembler::DecodeStatus;3031namespace {3233/// A disassembler class for ARC.34class ARCDisassembler : public MCDisassembler {35public:36std::unique_ptr<MCInstrInfo const> const MCII;3738ARCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,39MCInstrInfo const *MCII)40: MCDisassembler(STI, Ctx), MCII(MCII) {}4142DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,43ArrayRef<uint8_t> Bytes, uint64_t Address,44raw_ostream &CStream) const override;45};4647} // end anonymous namespace4849static bool readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,50uint64_t &Size, uint32_t &Insn) {51Size = 4;52// Read 2 16-bit values, but swap hi/lo parts.53Insn =54(Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);55return true;56}5758static bool readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,59uint64_t &Size, uint64_t &Insn) {60Size = 8;61Insn = ((uint64_t)Bytes[0] << 16) | ((uint64_t)Bytes[1] << 24) |62((uint64_t)Bytes[2] << 0) | ((uint64_t)Bytes[3] << 8) |63((uint64_t)Bytes[4] << 48) | ((uint64_t)Bytes[5] << 56) |64((uint64_t)Bytes[6] << 32) | ((uint64_t)Bytes[7] << 40);65return true;66}6768static bool readInstruction48(ArrayRef<uint8_t> Bytes, uint64_t Address,69uint64_t &Size, uint64_t &Insn) {70Size = 6;71Insn = ((uint64_t)Bytes[0] << 0) | ((uint64_t)Bytes[1] << 8) |72((uint64_t)Bytes[2] << 32) | ((uint64_t)Bytes[3] << 40) |73((uint64_t)Bytes[4] << 16) | ((uint64_t)Bytes[5] << 24);74return true;75}7677static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,78uint64_t &Size, uint32_t &Insn) {79Size = 2;80Insn = (Bytes[0] << 0) | (Bytes[1] << 8);81return true;82}8384template <unsigned B>85static DecodeStatus86DecodeSignedOperand(MCInst &Inst, unsigned InsnS, uint64_t Address = 0,87const MCDisassembler *Decoder = nullptr);8889template <unsigned B>90static DecodeStatus91DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS, uint64_t Address = 0,92const MCDisassembler *Decoder = nullptr);9394template <unsigned B>95static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,96uint64_t Address,97const MCDisassembler *Decoder);9899static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t,100const MCDisassembler *);101102static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t,103const MCDisassembler *);104105static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,106const MCDisassembler *);107108static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,109const MCDisassembler *);110111static DecodeStatus DecodeSOPwithRS12(MCInst &, uint64_t, uint64_t,112const MCDisassembler *);113114static DecodeStatus DecodeSOPwithRU6(MCInst &, uint64_t, uint64_t,115const MCDisassembler *);116117static DecodeStatus DecodeCCRU6Instruction(MCInst &, uint64_t, uint64_t,118const MCDisassembler *);119120static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,121const MCDisassembler *);122123static const uint16_t GPR32DecoderTable[] = {124ARC::R0, ARC::R1, ARC::R2, ARC::R3, ARC::R4, ARC::R5, ARC::R6,125ARC::R7, ARC::R8, ARC::R9, ARC::R10, ARC::R11, ARC::R12, ARC::R13,126ARC::R14, ARC::R15, ARC::R16, ARC::R17, ARC::R18, ARC::R19, ARC::R20,127ARC::R21, ARC::R22, ARC::R23, ARC::R24, ARC::R25, ARC::GP, ARC::FP,128ARC::SP, ARC::ILINK, ARC::R30, ARC::BLINK};129130static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,131uint64_t Address,132const MCDisassembler *Decoder) {133if (RegNo >= 32) {134LLVM_DEBUG(dbgs() << "Not a GPR32 register.");135return MCDisassembler::Fail;136}137138unsigned Reg = GPR32DecoderTable[RegNo];139Inst.addOperand(MCOperand::createReg(Reg));140return MCDisassembler::Success;141}142143static DecodeStatus DecodeGBR32ShortRegister(MCInst &Inst, unsigned RegNo,144uint64_t Address,145const MCDisassembler *Decoder) {146// Enumerates registers from ranges [r0-r3],[r12-r15].147if (RegNo > 3)148RegNo += 8; // 4 for r12, etc...149150return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);151}152153#include "ARCGenDisassemblerTables.inc"154155static unsigned decodeCField(unsigned Insn) {156return fieldFromInstruction(Insn, 6, 6);157}158159static unsigned decodeBField(unsigned Insn) {160return (fieldFromInstruction(Insn, 12, 3) << 3) |161fieldFromInstruction(Insn, 24, 3);162}163164static unsigned decodeAField(unsigned Insn) {165return fieldFromInstruction(Insn, 0, 6);166}167168static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,169const MCDisassembler *Dec) {170// We have the 9-bit immediate in the low bits, 6-bit register in high bits.171unsigned S9 = Insn & 0x1ff;172unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;173DecodeGPR32RegisterClass(Inst, R, Address, Dec);174Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9)));175return MCDisassembler::Success;176}177178static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,179uint64_t Value,180const MCDisassembler *Decoder) {181static const uint64_t AtLeast = 2;182return (nullptr != Decoder && Decoder->tryAddingSymbolicOperand(183Inst, Value, Address, true, 0, AtLeast, 0));184}185186static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,187uint64_t Offset,188const MCDisassembler *Decoder) {189uint64_t NextAddress = Address + Offset;190191if (!DecodeSymbolicOperand(Inst, Address, NextAddress, Decoder))192Inst.addOperand(MCOperand::createImm(Offset));193}194195template <unsigned B>196static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,197uint64_t Address,198const MCDisassembler *Decoder) {199200static_assert(B > 0, "field is empty");201DecodeSymbolicOperandOff(Inst, Address, SignExtend32<B>(InsnS), Decoder);202return MCDisassembler::Success;203}204205template <unsigned B>206static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,207uint64_t /*Address*/,208const MCDisassembler * /*Decoder*/) {209210static_assert(B > 0, "field is empty");211Inst.addOperand(MCOperand::createImm(212SignExtend32<B>(maskTrailingOnes<decltype(InsnS)>(B) & InsnS)));213return MCDisassembler::Success;214}215216template <unsigned B>217static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,218uint64_t /*Address*/,219const MCDisassembler * /*Decoder*/) {220221static_assert(B > 0, "field is empty");222const unsigned max = (1u << B) - 1;223Inst.addOperand(224MCOperand::createImm(InsnS < max ? static_cast<int>(InsnS) : -1));225return MCDisassembler::Success;226}227228static DecodeStatus DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn,229uint64_t Address,230const MCDisassembler *Decoder) {231unsigned SrcC, DstB, LImm;232DstB = decodeBField(Insn);233if (DstB != 62) {234LLVM_DEBUG(dbgs() << "Decoding StLImm found non-limm register.");235return MCDisassembler::Fail;236}237SrcC = decodeCField(Insn);238DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);239LImm = (Insn >> 32);240Inst.addOperand(MCOperand::createImm(LImm));241Inst.addOperand(MCOperand::createImm(0));242return MCDisassembler::Success;243}244245static DecodeStatus DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn,246uint64_t Address,247const MCDisassembler *Decoder) {248unsigned DstA, SrcB, LImm;249LLVM_DEBUG(dbgs() << "Decoding LdLImm:\n");250SrcB = decodeBField(Insn);251if (SrcB != 62) {252LLVM_DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");253return MCDisassembler::Fail;254}255DstA = decodeAField(Insn);256DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);257LImm = (Insn >> 32);258Inst.addOperand(MCOperand::createImm(LImm));259Inst.addOperand(MCOperand::createImm(0));260return MCDisassembler::Success;261}262263static DecodeStatus DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn,264uint64_t Address,265const MCDisassembler *Decoder) {266unsigned DstA, SrcB;267LLVM_DEBUG(dbgs() << "Decoding LdRLimm\n");268DstA = decodeAField(Insn);269DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);270SrcB = decodeBField(Insn);271DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);272if (decodeCField(Insn) != 62) {273LLVM_DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");274return MCDisassembler::Fail;275}276Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32)));277return MCDisassembler::Success;278}279280static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,281uint64_t Address,282const MCDisassembler *Decoder) {283LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");284using Field = decltype(Insn);285Field H = fieldFromInstruction(Insn, 5, 3) |286(fieldFromInstruction(Insn, 0, 2) << 3);287Field G = fieldFromInstruction(Insn, 8, 3) |288(fieldFromInstruction(Insn, 3, 2) << 3);289290auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,291Field Value) {292if (30 == RegNum) {293Inst.addOperand(MCOperand::createImm(Value));294return MCDisassembler::Success;295}296297return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);298};299300if (MCDisassembler::Success != DecodeRegisterOrImm(G, 0))301return MCDisassembler::Fail;302303return DecodeRegisterOrImm(H, Insn >> 16u);304}305306static DecodeStatus DecodeCCRU6Instruction(MCInst &Inst, uint64_t Insn,307uint64_t Address,308const MCDisassembler *Decoder) {309unsigned DstB;310LLVM_DEBUG(dbgs() << "Decoding CCRU6 instruction:\n");311DstB = decodeBField(Insn);312DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);313using Field = decltype(Insn);314Field U6Field = fieldFromInstruction(Insn, 6, 6);315Inst.addOperand(MCOperand::createImm(U6Field));316Field CCField = fieldFromInstruction(Insn, 0, 4);317Inst.addOperand(MCOperand::createImm(CCField));318return MCDisassembler::Success;319}320321static DecodeStatus DecodeSOPwithRU6(MCInst &Inst, uint64_t Insn,322uint64_t Address,323const MCDisassembler *Decoder) {324unsigned DstB = decodeBField(Insn);325DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);326using Field = decltype(Insn);327Field U6 = fieldFromInstruction(Insn, 6, 6);328Inst.addOperand(MCOperand::createImm(U6));329return MCDisassembler::Success;330}331332static DecodeStatus DecodeSOPwithRS12(MCInst &Inst, uint64_t Insn,333uint64_t Address,334const MCDisassembler *Decoder) {335unsigned DstB = decodeBField(Insn);336DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);337using Field = decltype(Insn);338Field Lower = fieldFromInstruction(Insn, 6, 6);339Field Upper = fieldFromInstruction(Insn, 0, 5);340Field Sign = fieldFromInstruction(Insn, 5, 1) ? -1 : 1;341Field Result = Sign * ((Upper << 6) + Lower);342Inst.addOperand(MCOperand::createImm(Result));343return MCDisassembler::Success;344}345346DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,347ArrayRef<uint8_t> Bytes,348uint64_t Address,349raw_ostream &cStream) const {350MCDisassembler::DecodeStatus Result;351if (Bytes.size() < 2) {352Size = 0;353return Fail;354}355uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;356// 0x00 -> 0x07 are 32-bit instructions.357// 0x08 -> 0x1F are 16-bit instructions.358if (DecodeByte < 0x08) {359// 32-bit instruction.360if (Bytes.size() < 4) {361// Did we decode garbage?362Size = 0;363return Fail;364}365if (Bytes.size() >= 8) {366// Attempt to decode 64-bit instruction.367uint64_t Insn64;368if (!readInstruction64(Bytes, Address, Size, Insn64))369return Fail;370Result =371decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);372if (Success == Result) {373LLVM_DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");374return Result;375}376LLVM_DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");377}378uint32_t Insn32;379if (!readInstruction32(Bytes, Address, Size, Insn32)) {380return Fail;381}382// Calling the auto-generated decoder function.383return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);384} else {385if (Bytes.size() >= 6) {386// Attempt to treat as instr. with limm data.387uint64_t Insn48;388if (!readInstruction48(Bytes, Address, Size, Insn48))389return Fail;390Result =391decodeInstruction(DecoderTable48, Instr, Insn48, Address, this, STI);392if (Success == Result) {393LLVM_DEBUG(394dbgs() << "Successfully decoded 16-bit instruction with limm.");395return Result;396}397LLVM_DEBUG(398dbgs() << "Not a 16-bit instruction with limm, try without it.");399}400401uint32_t Insn16;402if (!readInstruction16(Bytes, Address, Size, Insn16))403return Fail;404405// Calling the auto-generated decoder function.406return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);407}408}409410static MCDisassembler *createARCDisassembler(const Target &T,411const MCSubtargetInfo &STI,412MCContext &Ctx) {413return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());414}415416extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARCDisassembler() {417// Register the disassembler.418TargetRegistry::RegisterMCDisassembler(getTheARCTarget(),419createARCDisassembler);420}421422423