brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.7 KiB · f28c7d8 Raw
424 lines · cpp
1//===- ARCDisassembler.cpp - Disassembler for ARC ---------------*- C++ -*-===//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/// \file10/// This file is part of the ARC Disassembler.11///12//===----------------------------------------------------------------------===//13 14#include "ARC.h"15#include "ARCRegisterInfo.h"16#include "MCTargetDesc/ARCMCTargetDesc.h"17#include "TargetInfo/ARCTargetInfo.h"18#include "llvm/MC/MCContext.h"19#include "llvm/MC/MCDecoder.h"20#include "llvm/MC/MCDecoderOps.h"21#include "llvm/MC/MCDisassembler/MCDisassembler.h"22#include "llvm/MC/MCInst.h"23#include "llvm/MC/MCInstrInfo.h"24#include "llvm/MC/MCSubtargetInfo.h"25#include "llvm/MC/TargetRegistry.h"26 27using namespace llvm;28using namespace llvm::MCD;29 30#define DEBUG_TYPE "arc-disassembler"31 32using DecodeStatus = MCDisassembler::DecodeStatus;33 34namespace {35 36/// A disassembler class for ARC.37class ARCDisassembler : public MCDisassembler {38public:39  std::unique_ptr<MCInstrInfo const> const MCII;40 41  ARCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,42                  MCInstrInfo const *MCII)43      : MCDisassembler(STI, Ctx), MCII(MCII) {}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 50} // end anonymous namespace51 52static bool readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,53                              uint64_t &Size, uint32_t &Insn) {54  Size = 4;55  // Read 2 16-bit values, but swap hi/lo parts.56  Insn =57      (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);58  return true;59}60 61static bool readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,62                              uint64_t &Size, uint64_t &Insn) {63  Size = 8;64  Insn = ((uint64_t)Bytes[0] << 16) | ((uint64_t)Bytes[1] << 24) |65         ((uint64_t)Bytes[2] << 0) | ((uint64_t)Bytes[3] << 8) |66         ((uint64_t)Bytes[4] << 48) | ((uint64_t)Bytes[5] << 56) |67         ((uint64_t)Bytes[6] << 32) | ((uint64_t)Bytes[7] << 40);68  return true;69}70 71static bool readInstruction48(ArrayRef<uint8_t> Bytes, uint64_t Address,72                              uint64_t &Size, uint64_t &Insn) {73  Size = 6;74  Insn = ((uint64_t)Bytes[0] << 0) | ((uint64_t)Bytes[1] << 8) |75         ((uint64_t)Bytes[2] << 32) | ((uint64_t)Bytes[3] << 40) |76         ((uint64_t)Bytes[4] << 16) | ((uint64_t)Bytes[5] << 24);77  return true;78}79 80static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,81                              uint64_t &Size, uint32_t &Insn) {82  Size = 2;83  Insn = (Bytes[0] << 0) | (Bytes[1] << 8);84  return true;85}86 87template <unsigned B>88static DecodeStatus89DecodeSignedOperand(MCInst &Inst, unsigned InsnS, uint64_t Address = 0,90                    const MCDisassembler *Decoder = nullptr);91 92template <unsigned B>93static DecodeStatus94DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS, uint64_t Address = 0,95                      const MCDisassembler *Decoder = nullptr);96 97template <unsigned B>98static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,99                                        uint64_t Address,100                                        const MCDisassembler *Decoder);101 102static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t,103                                 const MCDisassembler *);104 105static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t,106                                            const MCDisassembler *);107 108static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,109                                            const MCDisassembler *);110 111static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,112                                             const MCDisassembler *);113 114static DecodeStatus DecodeSOPwithRS12(MCInst &, uint64_t, uint64_t,115                                      const MCDisassembler *);116 117static DecodeStatus DecodeSOPwithRU6(MCInst &, uint64_t, uint64_t,118                                     const MCDisassembler *);119 120static DecodeStatus DecodeCCRU6Instruction(MCInst &, uint64_t, uint64_t,121                                           const MCDisassembler *);122 123static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,124                                              const MCDisassembler *);125 126static const uint16_t GPR32DecoderTable[] = {127    ARC::R0,  ARC::R1,    ARC::R2,  ARC::R3,   ARC::R4,  ARC::R5,  ARC::R6,128    ARC::R7,  ARC::R8,    ARC::R9,  ARC::R10,  ARC::R11, ARC::R12, ARC::R13,129    ARC::R14, ARC::R15,   ARC::R16, ARC::R17,  ARC::R18, ARC::R19, ARC::R20,130    ARC::R21, ARC::R22,   ARC::R23, ARC::R24,  ARC::R25, ARC::GP,  ARC::FP,131    ARC::SP,  ARC::ILINK, ARC::R30, ARC::BLINK};132 133static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,134                                             uint64_t Address,135                                             const MCDisassembler *Decoder) {136  if (RegNo >= 32) {137    LLVM_DEBUG(dbgs() << "Not a GPR32 register.");138    return MCDisassembler::Fail;139  }140 141  unsigned Reg = GPR32DecoderTable[RegNo];142  Inst.addOperand(MCOperand::createReg(Reg));143  return MCDisassembler::Success;144}145 146static DecodeStatus DecodeGBR32ShortRegister(MCInst &Inst, unsigned RegNo,147                                             uint64_t Address,148                                             const MCDisassembler *Decoder) {149  // Enumerates registers from ranges [r0-r3],[r12-r15].150  if (RegNo > 3)151    RegNo += 8; // 4 for r12, etc...152 153  return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);154}155 156#include "ARCGenDisassemblerTables.inc"157 158static unsigned decodeCField(unsigned Insn) {159  return fieldFromInstruction(Insn, 6, 6);160}161 162static unsigned decodeBField(unsigned Insn) {163  return (fieldFromInstruction(Insn, 12, 3) << 3) |164         fieldFromInstruction(Insn, 24, 3);165}166 167static unsigned decodeAField(unsigned Insn) {168  return fieldFromInstruction(Insn, 0, 6);169}170 171static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,172                                 const MCDisassembler *Dec) {173  // We have the 9-bit immediate in the low bits, 6-bit register in high bits.174  unsigned S9 = Insn & 0x1ff;175  unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;176  DecodeGPR32RegisterClass(Inst, R, Address, Dec);177  Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9)));178  return MCDisassembler::Success;179}180 181static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,182                                  uint64_t Value,183                                  const MCDisassembler *Decoder) {184  static const uint64_t AtLeast = 2;185  return (nullptr != Decoder && Decoder->tryAddingSymbolicOperand(186                                    Inst, Value, Address, true, 0, AtLeast, 0));187}188 189static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,190                                     uint64_t Offset,191                                     const MCDisassembler *Decoder) {192  uint64_t NextAddress = Address + Offset;193 194  if (!DecodeSymbolicOperand(Inst, Address, NextAddress, Decoder))195    Inst.addOperand(MCOperand::createImm(Offset));196}197 198template <unsigned B>199static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,200                                        uint64_t Address,201                                        const MCDisassembler *Decoder) {202 203  static_assert(B > 0, "field is empty");204  DecodeSymbolicOperandOff(Inst, Address, SignExtend32<B>(InsnS), Decoder);205  return MCDisassembler::Success;206}207 208template <unsigned B>209static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,210                                        uint64_t /*Address*/,211                                        const MCDisassembler * /*Decoder*/) {212 213  static_assert(B > 0, "field is empty");214  Inst.addOperand(MCOperand::createImm(215      SignExtend32<B>(maskTrailingOnes<decltype(InsnS)>(B) & InsnS)));216  return MCDisassembler::Success;217}218 219template <unsigned B>220static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,221                                          uint64_t /*Address*/,222                                          const MCDisassembler * /*Decoder*/) {223 224  static_assert(B > 0, "field is empty");225  const unsigned max = (1u << B) - 1;226  Inst.addOperand(227      MCOperand::createImm(InsnS < max ? static_cast<int>(InsnS) : -1));228  return MCDisassembler::Success;229}230 231static DecodeStatus DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn,232                                            uint64_t Address,233                                            const MCDisassembler *Decoder) {234  unsigned SrcC, DstB, LImm;235  DstB = decodeBField(Insn);236  if (DstB != 62) {237    LLVM_DEBUG(dbgs() << "Decoding StLImm found non-limm register.");238    return MCDisassembler::Fail;239  }240  SrcC = decodeCField(Insn);241  DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);242  LImm = (Insn >> 32);243  Inst.addOperand(MCOperand::createImm(LImm));244  Inst.addOperand(MCOperand::createImm(0));245  return MCDisassembler::Success;246}247 248static DecodeStatus DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn,249                                            uint64_t Address,250                                            const MCDisassembler *Decoder) {251  unsigned DstA, SrcB, LImm;252  LLVM_DEBUG(dbgs() << "Decoding LdLImm:\n");253  SrcB = decodeBField(Insn);254  if (SrcB != 62) {255    LLVM_DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");256    return MCDisassembler::Fail;257  }258  DstA = decodeAField(Insn);259  DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);260  LImm = (Insn >> 32);261  Inst.addOperand(MCOperand::createImm(LImm));262  Inst.addOperand(MCOperand::createImm(0));263  return MCDisassembler::Success;264}265 266static DecodeStatus DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn,267                                             uint64_t Address,268                                             const MCDisassembler *Decoder) {269  unsigned DstA, SrcB;270  LLVM_DEBUG(dbgs() << "Decoding LdRLimm\n");271  DstA = decodeAField(Insn);272  DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);273  SrcB = decodeBField(Insn);274  DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);275  if (decodeCField(Insn) != 62) {276    LLVM_DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");277    return MCDisassembler::Fail;278  }279  Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32)));280  return MCDisassembler::Success;281}282 283static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,284                                              uint64_t Address,285                                              const MCDisassembler *Decoder) {286  LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");287  using Field = decltype(Insn);288  Field H = fieldFromInstruction(Insn, 5, 3) |289            (fieldFromInstruction(Insn, 0, 2) << 3);290  Field G = fieldFromInstruction(Insn, 8, 3) |291            (fieldFromInstruction(Insn, 3, 2) << 3);292 293  auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,294                                                       Field Value) {295    if (30 == RegNum) {296      Inst.addOperand(MCOperand::createImm(Value));297      return MCDisassembler::Success;298    }299 300    return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);301  };302 303  if (MCDisassembler::Success != DecodeRegisterOrImm(G, 0))304    return MCDisassembler::Fail;305 306  return DecodeRegisterOrImm(H, Insn >> 16u);307}308 309static DecodeStatus DecodeCCRU6Instruction(MCInst &Inst, uint64_t Insn,310                                           uint64_t Address,311                                           const MCDisassembler *Decoder) {312  unsigned DstB;313  LLVM_DEBUG(dbgs() << "Decoding CCRU6 instruction:\n");314  DstB = decodeBField(Insn);315  DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);316  using Field = decltype(Insn);317  Field U6Field = fieldFromInstruction(Insn, 6, 6);318  Inst.addOperand(MCOperand::createImm(U6Field));319  Field CCField = fieldFromInstruction(Insn, 0, 4);320  Inst.addOperand(MCOperand::createImm(CCField));321  return MCDisassembler::Success;322}323 324static DecodeStatus DecodeSOPwithRU6(MCInst &Inst, uint64_t Insn,325                                     uint64_t Address,326                                     const MCDisassembler *Decoder) {327  unsigned DstB = decodeBField(Insn);328  DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);329  using Field = decltype(Insn);330  Field U6 = fieldFromInstruction(Insn, 6, 6);331  Inst.addOperand(MCOperand::createImm(U6));332  return MCDisassembler::Success;333}334 335static DecodeStatus DecodeSOPwithRS12(MCInst &Inst, uint64_t Insn,336                                      uint64_t Address,337                                      const MCDisassembler *Decoder) {338  unsigned DstB = decodeBField(Insn);339  DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);340  using Field = decltype(Insn);341  Field Lower = fieldFromInstruction(Insn, 6, 6);342  Field Upper = fieldFromInstruction(Insn, 0, 5);343  Field Sign = fieldFromInstruction(Insn, 5, 1) ? -1 : 1;344  Field Result = Sign * ((Upper << 6) + Lower);345  Inst.addOperand(MCOperand::createImm(Result));346  return MCDisassembler::Success;347}348 349DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,350                                             ArrayRef<uint8_t> Bytes,351                                             uint64_t Address,352                                             raw_ostream &cStream) const {353  MCDisassembler::DecodeStatus Result;354  if (Bytes.size() < 2) {355    Size = 0;356    return Fail;357  }358  uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;359  // 0x00 -> 0x07 are 32-bit instructions.360  // 0x08 -> 0x1F are 16-bit instructions.361  if (DecodeByte < 0x08) {362    // 32-bit instruction.363    if (Bytes.size() < 4) {364      // Did we decode garbage?365      Size = 0;366      return Fail;367    }368    if (Bytes.size() >= 8) {369      // Attempt to decode 64-bit instruction.370      uint64_t Insn64;371      if (!readInstruction64(Bytes, Address, Size, Insn64))372        return Fail;373      Result =374          decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);375      if (Success == Result) {376        LLVM_DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");377        return Result;378      }379      LLVM_DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");380    }381    uint32_t Insn32;382    if (!readInstruction32(Bytes, Address, Size, Insn32)) {383      return Fail;384    }385    // Calling the auto-generated decoder function.386    return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);387  } else {388    if (Bytes.size() >= 6) {389      // Attempt to treat as instr. with limm data.390      uint64_t Insn48;391      if (!readInstruction48(Bytes, Address, Size, Insn48))392        return Fail;393      Result =394          decodeInstruction(DecoderTable48, Instr, Insn48, Address, this, STI);395      if (Success == Result) {396        LLVM_DEBUG(397            dbgs() << "Successfully decoded 16-bit instruction with limm.");398        return Result;399      }400      LLVM_DEBUG(401          dbgs() << "Not a 16-bit instruction with limm, try without it.");402    }403 404    uint32_t Insn16;405    if (!readInstruction16(Bytes, Address, Size, Insn16))406      return Fail;407 408    // Calling the auto-generated decoder function.409    return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);410  }411}412 413static MCDisassembler *createARCDisassembler(const Target &T,414                                             const MCSubtargetInfo &STI,415                                             MCContext &Ctx) {416  return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());417}418 419extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARCDisassembler() {420  // Register the disassembler.421  TargetRegistry::RegisterMCDisassembler(getTheARCTarget(),422                                         createARCDisassembler);423}424