brintos

brintos / llvm-project-archived public Read only

0
0
Text · 20.0 KiB · 7d22a04 Raw
523 lines · cpp
1//===-- XtensaDisassembler.cpp - Disassembler for Xtensa ------------------===//2//3//                     The LLVM Compiler Infrastructure4//5// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.6// See https://llvm.org/LICENSE.txt for license information.7// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception8//9//===----------------------------------------------------------------------===//10//11// This file implements the XtensaDisassembler class.12//13//===----------------------------------------------------------------------===//14 15#include "MCTargetDesc/XtensaMCTargetDesc.h"16#include "TargetInfo/XtensaTargetInfo.h"17#include "llvm/MC/MCContext.h"18#include "llvm/MC/MCDecoder.h"19#include "llvm/MC/MCDecoderOps.h"20#include "llvm/MC/MCDisassembler/MCDisassembler.h"21#include "llvm/MC/MCInst.h"22#include "llvm/MC/MCRegisterInfo.h"23#include "llvm/MC/MCSubtargetInfo.h"24#include "llvm/MC/TargetRegistry.h"25#include "llvm/Support/Endian.h"26 27using namespace llvm;28using namespace llvm::MCD;29 30#define DEBUG_TYPE "Xtensa-disassembler"31 32using DecodeStatus = MCDisassembler::DecodeStatus;33 34namespace {35 36class XtensaDisassembler : public MCDisassembler {37  bool IsLittleEndian;38 39public:40  XtensaDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool isLE)41      : MCDisassembler(STI, Ctx), IsLittleEndian(isLE) {}42 43  bool hasDensity() const { return STI.hasFeature(Xtensa::FeatureDensity); }44 45  DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,46                              ArrayRef<uint8_t> Bytes, uint64_t Address,47                              raw_ostream &CStream) const override;48};49} // end anonymous namespace50 51static MCDisassembler *createXtensaDisassembler(const Target &T,52                                                const MCSubtargetInfo &STI,53                                                MCContext &Ctx) {54  return new XtensaDisassembler(STI, Ctx, true);55}56 57extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaDisassembler() {58  TargetRegistry::RegisterMCDisassembler(getTheXtensaTarget(),59                                         createXtensaDisassembler);60}61 62const MCPhysReg ARDecoderTable[] = {63    Xtensa::A0,  Xtensa::SP,  Xtensa::A2,  Xtensa::A3, Xtensa::A4,  Xtensa::A5,64    Xtensa::A6,  Xtensa::A7,  Xtensa::A8,  Xtensa::A9, Xtensa::A10, Xtensa::A11,65    Xtensa::A12, Xtensa::A13, Xtensa::A14, Xtensa::A15};66 67static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo,68                                          uint64_t Address,69                                          const void *Decoder) {70  if (RegNo >= std::size(ARDecoderTable))71    return MCDisassembler::Fail;72 73  MCPhysReg Reg = ARDecoderTable[RegNo];74  Inst.addOperand(MCOperand::createReg(Reg));75  return MCDisassembler::Success;76}77 78static DecodeStatus DecodeMRRegisterClass(MCInst &Inst, uint64_t RegNo,79                                          uint64_t Address,80                                          const void *Decoder) {81  if (RegNo > 3)82    return MCDisassembler::Fail;83 84  MCPhysReg Reg = Xtensa::M0 + RegNo;85  Inst.addOperand(MCOperand::createReg(Reg));86  return MCDisassembler::Success;87}88 89static DecodeStatus DecodeMR01RegisterClass(MCInst &Inst, uint64_t RegNo,90                                            uint64_t Address,91                                            const void *Decoder) {92  if (RegNo > 1)93    return MCDisassembler::Fail;94 95  MCPhysReg Reg = Xtensa::M0 + RegNo;96  Inst.addOperand(MCOperand::createReg(Reg));97  return MCDisassembler::Success;98}99 100static DecodeStatus DecodeMR23RegisterClass(MCInst &Inst, uint64_t RegNo,101                                            uint64_t Address,102                                            const void *Decoder) {103  if (RegNo > 1)104    return MCDisassembler::Fail;105 106  MCPhysReg Reg = Xtensa::M2 + RegNo;107  Inst.addOperand(MCOperand::createReg(Reg));108  return MCDisassembler::Success;109}110 111static DecodeStatus DecodeFPRRegisterClass(MCInst &Inst, uint64_t RegNo,112                                           uint64_t Address,113                                           const void *Decoder) {114  if (RegNo > 15)115    return MCDisassembler::Fail;116 117  MCPhysReg Reg = Xtensa::F0 + RegNo;118  Inst.addOperand(MCOperand::createReg(Reg));119  return MCDisassembler::Success;120}121 122static DecodeStatus DecodeURRegisterClass(MCInst &Inst, uint64_t RegNo,123                                          uint64_t Address,124                                          const MCDisassembler *Decoder) {125  if (RegNo > 255)126    return MCDisassembler::Fail;127 128  Xtensa::RegisterAccessType RAType = Inst.getOpcode() == Xtensa::WUR129                                          ? Xtensa::REGISTER_WRITE130                                          : Xtensa::REGISTER_READ;131 132  const XtensaDisassembler *Dis =133      static_cast<const XtensaDisassembler *>(Decoder);134  const MCRegisterInfo *MRI = Dis->getContext().getRegisterInfo();135  MCPhysReg Reg = Xtensa::getUserRegister(RegNo, *MRI);136  if (!Xtensa::checkRegister(Reg, Decoder->getSubtargetInfo().getFeatureBits(),137                             RAType))138    return MCDisassembler::Fail;139 140  Inst.addOperand(MCOperand::createReg(Reg));141  return MCDisassembler::Success;142}143 144struct DecodeRegister {145  MCPhysReg Reg;146  uint32_t RegNo;147};148 149const DecodeRegister SRDecoderTable[] = {150    {Xtensa::LBEG, 0},         {Xtensa::LEND, 1},151    {Xtensa::LCOUNT, 2},       {Xtensa::SAR, 3},152    {Xtensa::BREG, 4},         {Xtensa::LITBASE, 5},153    {Xtensa::SCOMPARE1, 12},   {Xtensa::ACCLO, 16},154    {Xtensa::ACCHI, 17},       {Xtensa::M0, 32},155    {Xtensa::M1, 33},          {Xtensa::M2, 34},156    {Xtensa::M3, 35},          {Xtensa::WINDOWBASE, 72},157    {Xtensa::WINDOWSTART, 73}, {Xtensa::IBREAKENABLE, 96},158    {Xtensa::MEMCTL, 97},      {Xtensa::ATOMCTL, 99},159    {Xtensa::DDR, 104},        {Xtensa::IBREAKA0, 128},160    {Xtensa::IBREAKA1, 129},   {Xtensa::DBREAKA0, 144},161    {Xtensa::DBREAKA1, 145},   {Xtensa::DBREAKC0, 160},162    {Xtensa::DBREAKC1, 161},   {Xtensa::CONFIGID0, 176},163    {Xtensa::EPC1, 177},       {Xtensa::EPC2, 178},164    {Xtensa::EPC3, 179},       {Xtensa::EPC4, 180},165    {Xtensa::EPC5, 181},       {Xtensa::EPC6, 182},166    {Xtensa::EPC7, 183},       {Xtensa::DEPC, 192},167    {Xtensa::EPS2, 194},       {Xtensa::EPS3, 195},168    {Xtensa::EPS4, 196},       {Xtensa::EPS5, 197},169    {Xtensa::EPS6, 198},       {Xtensa::EPS7, 199},170    {Xtensa::CONFIGID1, 208},  {Xtensa::EXCSAVE1, 209},171    {Xtensa::EXCSAVE2, 210},   {Xtensa::EXCSAVE3, 211},172    {Xtensa::EXCSAVE4, 212},   {Xtensa::EXCSAVE5, 213},173    {Xtensa::EXCSAVE6, 214},   {Xtensa::EXCSAVE7, 215},174    {Xtensa::CPENABLE, 224},   {Xtensa::INTERRUPT, 226},175    {Xtensa::INTCLEAR, 227},   {Xtensa::INTENABLE, 228},176    {Xtensa::PS, 230},         {Xtensa::VECBASE, 231},177    {Xtensa::EXCCAUSE, 232},   {Xtensa::DEBUGCAUSE, 233},178    {Xtensa::CCOUNT, 234},     {Xtensa::PRID, 235},179    {Xtensa::ICOUNT, 236},     {Xtensa::ICOUNTLEVEL, 237},180    {Xtensa::EXCVADDR, 238},   {Xtensa::CCOMPARE0, 240},181    {Xtensa::CCOMPARE1, 241},  {Xtensa::CCOMPARE2, 242},182    {Xtensa::MISC0, 244},      {Xtensa::MISC1, 245},183    {Xtensa::MISC2, 246},      {Xtensa::MISC3, 247}};184 185static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo,186                                          uint64_t Address,187                                          const MCDisassembler *Decoder) {188  if (RegNo > 255)189    return MCDisassembler::Fail;190 191  Xtensa::RegisterAccessType RAType =192      Inst.getOpcode() == Xtensa::WSR193          ? Xtensa::REGISTER_WRITE194          : (Inst.getOpcode() == Xtensa::RSR ? Xtensa::REGISTER_READ195                                             : Xtensa::REGISTER_EXCHANGE);196 197  for (unsigned i = 0; i < std::size(SRDecoderTable); i++) {198    if (SRDecoderTable[i].RegNo == RegNo) {199      MCPhysReg Reg = SRDecoderTable[i].Reg;200 201      // Handle special case. The INTERRUPT/INTSET registers use the same202      // encoding, but INTERRUPT used for read and INTSET for write.203      if (Reg == Xtensa::INTERRUPT && RAType == Xtensa::REGISTER_WRITE) {204        Reg = Xtensa::INTSET;205      }206 207      if (!Xtensa::checkRegister(208              Reg, Decoder->getSubtargetInfo().getFeatureBits(), RAType))209        return MCDisassembler::Fail;210 211      Inst.addOperand(MCOperand::createReg(Reg));212      return MCDisassembler::Success;213    }214  }215 216  return MCDisassembler::Fail;217}218 219static DecodeStatus DecodeBRRegisterClass(MCInst &Inst, uint64_t RegNo,220                                          uint64_t Address,221                                          const void *Decoder) {222  if (RegNo > 15)223    return MCDisassembler::Fail;224 225  MCPhysReg Reg = Xtensa::B0 + RegNo;226  Inst.addOperand(MCOperand::createReg(Reg));227  return MCDisassembler::Success;228}229 230static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,231                                     uint64_t Address, uint64_t Offset,232                                     uint64_t InstSize, MCInst &MI,233                                     const void *Decoder) {234  const MCDisassembler *Dis = static_cast<const MCDisassembler *>(Decoder);235  return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch, Offset,236                                       /*OpSize=*/0, InstSize);237}238 239static DecodeStatus decodeCallOperand(MCInst &Inst, uint64_t Imm,240                                      int64_t Address, const void *Decoder) {241  assert(isUInt<18>(Imm) && "Invalid immediate");242  Inst.addOperand(243      MCOperand::createImm(SignExtend64<20>(Imm << 2) + (Address & 0x3)));244  return MCDisassembler::Success;245}246 247static DecodeStatus decodeJumpOperand(MCInst &Inst, uint64_t Imm,248                                      int64_t Address, const void *Decoder) {249  assert(isUInt<18>(Imm) && "Invalid immediate");250  Inst.addOperand(MCOperand::createImm(SignExtend64<18>(Imm)));251  return MCDisassembler::Success;252}253 254static DecodeStatus decodeBranchOperand(MCInst &Inst, uint64_t Imm,255                                        int64_t Address, const void *Decoder) {256  switch (Inst.getOpcode()) {257  case Xtensa::BEQZ:258  case Xtensa::BGEZ:259  case Xtensa::BLTZ:260  case Xtensa::BNEZ:261    assert(isUInt<12>(Imm) && "Invalid immediate");262    if (!tryAddingSymbolicOperand(SignExtend64<12>(Imm) + 4 + Address, true,263                                  Address, 0, 3, Inst, Decoder))264      Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm)));265    break;266  default:267    assert(isUInt<8>(Imm) && "Invalid immediate");268    if (!tryAddingSymbolicOperand(SignExtend64<8>(Imm) + 4 + Address, true,269                                  Address, 0, 3, Inst, Decoder))270      Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));271  }272  return MCDisassembler::Success;273}274 275static DecodeStatus decodeLoopOperand(MCInst &Inst, uint64_t Imm,276                                      int64_t Address, const void *Decoder) {277 278  assert(isUInt<8>(Imm) && "Invalid immediate");279  if (!tryAddingSymbolicOperand(Imm + 4 + Address, true, Address, 0, 3, Inst,280                                Decoder))281    Inst.addOperand(MCOperand::createImm(Imm));282  return MCDisassembler::Success;283}284 285static DecodeStatus decodeL32ROperand(MCInst &Inst, uint64_t Imm,286                                      int64_t Address, const void *Decoder) {287 288  assert(isUInt<16>(Imm) && "Invalid immediate");289  Inst.addOperand(MCOperand::createImm(290      SignExtend64<17>((Imm << 2) + 0x40000 + (Address & 0x3))));291  return MCDisassembler::Success;292}293 294static DecodeStatus decodeImm8Operand(MCInst &Inst, uint64_t Imm,295                                      int64_t Address, const void *Decoder) {296  assert(isUInt<8>(Imm) && "Invalid immediate");297  Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));298  return MCDisassembler::Success;299}300 301static DecodeStatus decodeImm8_sh8Operand(MCInst &Inst, uint64_t Imm,302                                          int64_t Address,303                                          const void *Decoder) {304  assert(isUInt<8>(Imm) && "Invalid immediate");305  Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 8)));306  return MCDisassembler::Success;307}308 309static DecodeStatus decodeImm12Operand(MCInst &Inst, uint64_t Imm,310                                       int64_t Address, const void *Decoder) {311  assert(isUInt<12>(Imm) && "Invalid immediate");312  Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm)));313  return MCDisassembler::Success;314}315 316static DecodeStatus decodeUimm4Operand(MCInst &Inst, uint64_t Imm,317                                       int64_t Address, const void *Decoder) {318  assert(isUInt<4>(Imm) && "Invalid immediate");319  Inst.addOperand(MCOperand::createImm(Imm));320  return MCDisassembler::Success;321}322 323static DecodeStatus decodeUimm5Operand(MCInst &Inst, uint64_t Imm,324                                       int64_t Address, const void *Decoder) {325  assert(isUInt<5>(Imm) && "Invalid immediate");326  Inst.addOperand(MCOperand::createImm(Imm));327  return MCDisassembler::Success;328}329 330static DecodeStatus decodeImm1_16Operand(MCInst &Inst, uint64_t Imm,331                                         int64_t Address, const void *Decoder) {332  assert(isUInt<4>(Imm) && "Invalid immediate");333  Inst.addOperand(MCOperand::createImm(Imm + 1));334  return MCDisassembler::Success;335}336 337static DecodeStatus decodeImm1n_15Operand(MCInst &Inst, uint64_t Imm,338                                          int64_t Address,339                                          const void *Decoder) {340  assert(isUInt<4>(Imm) && "Invalid immediate");341  if (!Imm)342    Inst.addOperand(MCOperand::createImm(-1));343  else344    Inst.addOperand(MCOperand::createImm(Imm));345  return MCDisassembler::Success;346}347 348static DecodeStatus decodeImm32n_95Operand(MCInst &Inst, uint64_t Imm,349                                           int64_t Address,350                                           const void *Decoder) {351  assert(isUInt<7>(Imm) && "Invalid immediate");352  if ((Imm & 0x60) == 0x60)353    Inst.addOperand(MCOperand::createImm((~0x1f) | Imm));354  else355    Inst.addOperand(MCOperand::createImm(Imm));356  return MCDisassembler::Success;357}358 359static DecodeStatus decodeImm8n_7Operand(MCInst &Inst, uint64_t Imm,360                                         int64_t Address, const void *Decoder) {361  assert(isUInt<4>(Imm) && "Invalid immediate");362  Inst.addOperand(MCOperand::createImm(Imm > 7 ? Imm - 16 : Imm));363  return MCDisassembler::Success;364}365 366static DecodeStatus decodeImm64n_4nOperand(MCInst &Inst, uint64_t Imm,367                                           int64_t Address,368                                           const void *Decoder) {369  assert(isUInt<6>(Imm) && ((Imm & 0x3) == 0) && "Invalid immediate");370  Inst.addOperand(MCOperand::createImm((~0x3f) | (Imm)));371  return MCDisassembler::Success;372}373 374static DecodeStatus decodeEntry_Imm12OpValue(MCInst &Inst, uint64_t Imm,375                                             int64_t Address,376                                             const void *Decoder) {377  assert(isUInt<15>(Imm) && ((Imm & 0x7) == 0) && "Invalid immediate");378  Inst.addOperand(MCOperand::createImm(Imm));379  return MCDisassembler::Success;380}381 382static DecodeStatus decodeShimm1_31Operand(MCInst &Inst, uint64_t Imm,383                                           int64_t Address,384                                           const void *Decoder) {385  assert(isUInt<5>(Imm) && "Invalid immediate");386  Inst.addOperand(MCOperand::createImm(32 - Imm));387  return MCDisassembler::Success;388}389 390static int64_t TableB4const[16] = {-1, 1,  2,  3,  4,  5,  6,   7,391                                   8,  10, 12, 16, 32, 64, 128, 256};392static DecodeStatus decodeB4constOperand(MCInst &Inst, uint64_t Imm,393                                         int64_t Address, const void *Decoder) {394  assert(isUInt<4>(Imm) && "Invalid immediate");395 396  Inst.addOperand(MCOperand::createImm(TableB4const[Imm]));397  return MCDisassembler::Success;398}399 400static int64_t TableB4constu[16] = {32768, 65536, 2,  3,  4,  5,  6,   7,401                                    8,     10,    12, 16, 32, 64, 128, 256};402static DecodeStatus decodeB4constuOperand(MCInst &Inst, uint64_t Imm,403                                          int64_t Address,404                                          const void *Decoder) {405  assert(isUInt<4>(Imm) && "Invalid immediate");406 407  Inst.addOperand(MCOperand::createImm(TableB4constu[Imm]));408  return MCDisassembler::Success;409}410 411static DecodeStatus decodeImm7_22Operand(MCInst &Inst, uint64_t Imm,412                                         int64_t Address, const void *Decoder) {413  assert(isUInt<4>(Imm) && "Invalid immediate");414  Inst.addOperand(MCOperand::createImm(Imm + 7));415  return MCDisassembler::Success;416}417 418static DecodeStatus decodeMem8Operand(MCInst &Inst, uint64_t Imm,419                                      int64_t Address, const void *Decoder) {420  assert(isUInt<12>(Imm) && "Invalid immediate");421  DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);422  Inst.addOperand(MCOperand::createImm((Imm >> 4) & 0xff));423  return MCDisassembler::Success;424}425 426static DecodeStatus decodeMem16Operand(MCInst &Inst, uint64_t Imm,427                                       int64_t Address, const void *Decoder) {428  assert(isUInt<12>(Imm) && "Invalid immediate");429  DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);430  Inst.addOperand(MCOperand::createImm((Imm >> 3) & 0x1fe));431  return MCDisassembler::Success;432}433 434static DecodeStatus decodeMem32Operand(MCInst &Inst, uint64_t Imm,435                                       int64_t Address, const void *Decoder) {436  assert(isUInt<12>(Imm) && "Invalid immediate");437  DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);438  Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3fc));439  return MCDisassembler::Success;440}441 442static DecodeStatus decodeMem32nOperand(MCInst &Inst, uint64_t Imm,443                                        int64_t Address, const void *Decoder) {444  assert(isUInt<8>(Imm) && "Invalid immediate");445  DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);446  Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3c));447  return MCDisassembler::Success;448}449 450/// Read two bytes from the ArrayRef and return 16 bit data sorted451/// according to the given endianness.452static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,453                                      uint64_t &Size, uint64_t &Insn,454                                      bool IsLittleEndian) {455  // We want to read exactly 2 Bytes of data.456  if (Bytes.size() < 2) {457    Size = 0;458    return MCDisassembler::Fail;459  }460 461  if (!IsLittleEndian) {462    report_fatal_error("Big-endian mode currently is not supported!");463  } else {464    Insn = (Bytes[1] << 8) | Bytes[0];465  }466 467  return MCDisassembler::Success;468}469 470/// Read three bytes from the ArrayRef and return 24 bit data471static DecodeStatus readInstruction24(ArrayRef<uint8_t> Bytes, uint64_t Address,472                                      uint64_t &Size, uint64_t &Insn,473                                      bool IsLittleEndian) {474  // We want to read exactly 3 Bytes of data.475  if (Bytes.size() < 3) {476    Size = 0;477    return MCDisassembler::Fail;478  }479 480  if (!IsLittleEndian) {481    report_fatal_error("Big-endian mode currently is not supported!");482  } else {483    Insn = (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0);484  }485 486  return MCDisassembler::Success;487}488 489#include "XtensaGenDisassemblerTables.inc"490 491DecodeStatus XtensaDisassembler::getInstruction(MCInst &MI, uint64_t &Size,492                                                ArrayRef<uint8_t> Bytes,493                                                uint64_t Address,494                                                raw_ostream &CS) const {495  uint64_t Insn;496  DecodeStatus Result;497 498  // Parse 16-bit instructions499  if (hasDensity()) {500    Result = readInstruction16(Bytes, Address, Size, Insn, IsLittleEndian);501    if (Result == MCDisassembler::Fail)502      return MCDisassembler::Fail;503    LLVM_DEBUG(dbgs() << "Trying Xtensa 16-bit instruction table :\n");504    Result = decodeInstruction(DecoderTable16, MI, Insn, Address, this, STI);505    if (Result != MCDisassembler::Fail) {506      Size = 2;507      return Result;508    }509  }510 511  // Parse Core 24-bit instructions512  Result = readInstruction24(Bytes, Address, Size, Insn, IsLittleEndian);513  if (Result == MCDisassembler::Fail)514    return MCDisassembler::Fail;515  LLVM_DEBUG(dbgs() << "Trying Xtensa 24-bit instruction table :\n");516  Result = decodeInstruction(DecoderTable24, MI, Insn, Address, this, STI);517  if (Result != MCDisassembler::Fail) {518    Size = 3;519    return Result;520  }521  return Result;522}523