Path: blob/main/contrib/llvm-project/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
35295 views
//===-- XtensaDisassembler.cpp - Disassembler for Xtensa ------------------===//1//2// The LLVM Compiler Infrastructure3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9//10// This file implements the XtensaDisassembler class.11//12//===----------------------------------------------------------------------===//1314#include "MCTargetDesc/XtensaMCTargetDesc.h"15#include "TargetInfo/XtensaTargetInfo.h"16#include "llvm/MC/MCContext.h"17#include "llvm/MC/MCDecoderOps.h"18#include "llvm/MC/MCDisassembler/MCDisassembler.h"19#include "llvm/MC/MCInst.h"20#include "llvm/MC/MCRegisterInfo.h"21#include "llvm/MC/MCSubtargetInfo.h"22#include "llvm/MC/TargetRegistry.h"23#include "llvm/Support/Endian.h"2425using namespace llvm;2627#define DEBUG_TYPE "Xtensa-disassembler"2829using DecodeStatus = MCDisassembler::DecodeStatus;3031namespace {3233class XtensaDisassembler : public MCDisassembler {34bool IsLittleEndian;3536public:37XtensaDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool isLE)38: MCDisassembler(STI, Ctx), IsLittleEndian(isLE) {}3940bool hasDensity() const {41return STI.hasFeature(Xtensa::FeatureDensity);42}4344DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,45ArrayRef<uint8_t> Bytes, uint64_t Address,46raw_ostream &CStream) const override;47};48} // end anonymous namespace4950static MCDisassembler *createXtensaDisassembler(const Target &T,51const MCSubtargetInfo &STI,52MCContext &Ctx) {53return new XtensaDisassembler(STI, Ctx, true);54}5556extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaDisassembler() {57TargetRegistry::RegisterMCDisassembler(getTheXtensaTarget(),58createXtensaDisassembler);59}6061static const unsigned ARDecoderTable[] = {62Xtensa::A0, Xtensa::SP, Xtensa::A2, Xtensa::A3, Xtensa::A4, Xtensa::A5,63Xtensa::A6, Xtensa::A7, Xtensa::A8, Xtensa::A9, Xtensa::A10, Xtensa::A11,64Xtensa::A12, Xtensa::A13, Xtensa::A14, Xtensa::A15};6566static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo,67uint64_t Address,68const void *Decoder) {69if (RegNo >= std::size(ARDecoderTable))70return MCDisassembler::Fail;7172unsigned Reg = ARDecoderTable[RegNo];73Inst.addOperand(MCOperand::createReg(Reg));74return MCDisassembler::Success;75}7677static const unsigned SRDecoderTable[] = {Xtensa::SAR, 3};7879static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo,80uint64_t Address,81const void *Decoder) {82if (RegNo > 255)83return MCDisassembler::Fail;8485for (unsigned i = 0; i < std::size(SRDecoderTable); i += 2) {86if (SRDecoderTable[i + 1] == RegNo) {87unsigned Reg = SRDecoderTable[i];88Inst.addOperand(MCOperand::createReg(Reg));89return MCDisassembler::Success;90}91}9293return MCDisassembler::Fail;94}9596static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,97uint64_t Address, uint64_t Offset,98uint64_t InstSize, MCInst &MI,99const void *Decoder) {100const MCDisassembler *Dis = static_cast<const MCDisassembler *>(Decoder);101return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch, Offset, /*OpSize=*/0,102InstSize);103}104105static DecodeStatus decodeCallOperand(MCInst &Inst, uint64_t Imm,106int64_t Address, const void *Decoder) {107assert(isUInt<18>(Imm) && "Invalid immediate");108Inst.addOperand(MCOperand::createImm(SignExtend64<20>(Imm << 2)));109return MCDisassembler::Success;110}111112static DecodeStatus decodeJumpOperand(MCInst &Inst, uint64_t Imm,113int64_t Address, const void *Decoder) {114assert(isUInt<18>(Imm) && "Invalid immediate");115Inst.addOperand(MCOperand::createImm(SignExtend64<18>(Imm)));116return MCDisassembler::Success;117}118119static DecodeStatus decodeBranchOperand(MCInst &Inst, uint64_t Imm,120int64_t Address, const void *Decoder) {121switch (Inst.getOpcode()) {122case Xtensa::BEQZ:123case Xtensa::BGEZ:124case Xtensa::BLTZ:125case Xtensa::BNEZ:126assert(isUInt<12>(Imm) && "Invalid immediate");127if (!tryAddingSymbolicOperand(SignExtend64<12>(Imm) + 4 + Address, true,128Address, 0, 3, Inst, Decoder))129Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm)));130break;131default:132assert(isUInt<8>(Imm) && "Invalid immediate");133if (!tryAddingSymbolicOperand(SignExtend64<8>(Imm) + 4 + Address, true,134Address, 0, 3, Inst, Decoder))135Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));136}137return MCDisassembler::Success;138}139140static DecodeStatus decodeL32ROperand(MCInst &Inst, uint64_t Imm,141int64_t Address, const void *Decoder) {142143assert(isUInt<16>(Imm) && "Invalid immediate");144Inst.addOperand(MCOperand::createImm(145SignExtend64<17>((Imm << 2) + 0x40000 + (Address & 0x3))));146return MCDisassembler::Success;147}148149static DecodeStatus decodeImm8Operand(MCInst &Inst, uint64_t Imm,150int64_t Address, const void *Decoder) {151assert(isUInt<8>(Imm) && "Invalid immediate");152Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));153return MCDisassembler::Success;154}155156static DecodeStatus decodeImm8_sh8Operand(MCInst &Inst, uint64_t Imm,157int64_t Address,158const void *Decoder) {159assert(isUInt<8>(Imm) && "Invalid immediate");160Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 8)));161return MCDisassembler::Success;162}163164static DecodeStatus decodeImm12Operand(MCInst &Inst, uint64_t Imm,165int64_t Address, const void *Decoder) {166assert(isUInt<12>(Imm) && "Invalid immediate");167Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm)));168return MCDisassembler::Success;169}170171static DecodeStatus decodeUimm4Operand(MCInst &Inst, uint64_t Imm,172int64_t Address, const void *Decoder) {173assert(isUInt<4>(Imm) && "Invalid immediate");174Inst.addOperand(MCOperand::createImm(Imm));175return MCDisassembler::Success;176}177178static DecodeStatus decodeUimm5Operand(MCInst &Inst, uint64_t Imm,179int64_t Address, const void *Decoder) {180assert(isUInt<5>(Imm) && "Invalid immediate");181Inst.addOperand(MCOperand::createImm(Imm));182return MCDisassembler::Success;183}184185static DecodeStatus decodeImm1_16Operand(MCInst &Inst, uint64_t Imm,186int64_t Address, const void *Decoder) {187assert(isUInt<4>(Imm) && "Invalid immediate");188Inst.addOperand(MCOperand::createImm(Imm + 1));189return MCDisassembler::Success;190}191192static DecodeStatus decodeShimm1_31Operand(MCInst &Inst, uint64_t Imm,193int64_t Address,194const void *Decoder) {195assert(isUInt<5>(Imm) && "Invalid immediate");196Inst.addOperand(MCOperand::createImm(32 - Imm));197return MCDisassembler::Success;198}199200static int64_t TableB4const[16] = {-1, 1, 2, 3, 4, 5, 6, 7,2018, 10, 12, 16, 32, 64, 128, 256};202static DecodeStatus decodeB4constOperand(MCInst &Inst, uint64_t Imm,203int64_t Address, const void *Decoder) {204assert(isUInt<4>(Imm) && "Invalid immediate");205206Inst.addOperand(MCOperand::createImm(TableB4const[Imm]));207return MCDisassembler::Success;208}209210static int64_t TableB4constu[16] = {32768, 65536, 2, 3, 4, 5, 6, 7,2118, 10, 12, 16, 32, 64, 128, 256};212static DecodeStatus decodeB4constuOperand(MCInst &Inst, uint64_t Imm,213int64_t Address,214const void *Decoder) {215assert(isUInt<4>(Imm) && "Invalid immediate");216217Inst.addOperand(MCOperand::createImm(TableB4constu[Imm]));218return MCDisassembler::Success;219}220221static DecodeStatus decodeMem8Operand(MCInst &Inst, uint64_t Imm,222int64_t Address, const void *Decoder) {223assert(isUInt<12>(Imm) && "Invalid immediate");224DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);225Inst.addOperand(MCOperand::createImm((Imm >> 4) & 0xff));226return MCDisassembler::Success;227}228229static DecodeStatus decodeMem16Operand(MCInst &Inst, uint64_t Imm,230int64_t Address, const void *Decoder) {231assert(isUInt<12>(Imm) && "Invalid immediate");232DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);233Inst.addOperand(MCOperand::createImm((Imm >> 3) & 0x1fe));234return MCDisassembler::Success;235}236237static DecodeStatus decodeMem32Operand(MCInst &Inst, uint64_t Imm,238int64_t Address, const void *Decoder) {239assert(isUInt<12>(Imm) && "Invalid immediate");240DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);241Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3fc));242return MCDisassembler::Success;243}244245/// Read three bytes from the ArrayRef and return 24 bit data246static DecodeStatus readInstruction24(ArrayRef<uint8_t> Bytes, uint64_t Address,247uint64_t &Size, uint32_t &Insn,248bool IsLittleEndian) {249// We want to read exactly 3 Bytes of data.250if (Bytes.size() < 3) {251Size = 0;252return MCDisassembler::Fail;253}254255if (!IsLittleEndian) {256report_fatal_error("Big-endian mode currently is not supported!");257} else {258Insn = (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0);259}260261Size = 3;262return MCDisassembler::Success;263}264265#include "XtensaGenDisassemblerTables.inc"266267DecodeStatus XtensaDisassembler::getInstruction(MCInst &MI, uint64_t &Size,268ArrayRef<uint8_t> Bytes,269uint64_t Address,270raw_ostream &CS) const {271uint32_t Insn;272DecodeStatus Result;273274Result = readInstruction24(Bytes, Address, Size, Insn, IsLittleEndian);275if (Result == MCDisassembler::Fail)276return MCDisassembler::Fail;277LLVM_DEBUG(dbgs() << "Trying Xtensa 24-bit instruction table :\n");278Result = decodeInstruction(DecoderTable24, MI, Insn, Address, this, STI);279return Result;280}281282283