brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.5 KiB · e6666e8 Raw
376 lines · cpp
1//===-- MSP430Disassembler.cpp - Disassembler for MSP430 ------------------===//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// This file implements the MSP430Disassembler class.10//11//===----------------------------------------------------------------------===//12 13#include "MCTargetDesc/MSP430MCTargetDesc.h"14#include "MSP430.h"15#include "TargetInfo/MSP430TargetInfo.h"16#include "llvm/MC/MCContext.h"17#include "llvm/MC/MCDecoder.h"18#include "llvm/MC/MCDecoderOps.h"19#include "llvm/MC/MCDisassembler/MCDisassembler.h"20#include "llvm/MC/MCInst.h"21#include "llvm/MC/MCSubtargetInfo.h"22#include "llvm/MC/TargetRegistry.h"23#include "llvm/Support/Compiler.h"24#include "llvm/Support/Endian.h"25 26using namespace llvm;27using namespace llvm::MCD;28 29#define DEBUG_TYPE "msp430-disassembler"30 31typedef MCDisassembler::DecodeStatus DecodeStatus;32 33namespace {34class MSP430Disassembler : public MCDisassembler {35  DecodeStatus getInstructionI(MCInst &MI, uint64_t &Size,36                               ArrayRef<uint8_t> Bytes, uint64_t Address,37                               raw_ostream &CStream) const;38 39  DecodeStatus getInstructionII(MCInst &MI, uint64_t &Size,40                                ArrayRef<uint8_t> Bytes, uint64_t Address,41                                raw_ostream &CStream) const;42 43  DecodeStatus getInstructionCJ(MCInst &MI, uint64_t &Size,44                                ArrayRef<uint8_t> Bytes, uint64_t Address,45                                raw_ostream &CStream) const;46 47public:48  MSP430Disassembler(const MCSubtargetInfo &STI, MCContext &Ctx)49      : MCDisassembler(STI, Ctx) {}50 51  DecodeStatus getInstruction(MCInst &MI, uint64_t &Size,52                              ArrayRef<uint8_t> Bytes, uint64_t Address,53                              raw_ostream &CStream) const override;54};55} // end anonymous namespace56 57static MCDisassembler *createMSP430Disassembler(const Target &T,58                                                const MCSubtargetInfo &STI,59                                                MCContext &Ctx) {60  return new MSP430Disassembler(STI, Ctx);61}62 63extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void64LLVMInitializeMSP430Disassembler() {65  TargetRegistry::RegisterMCDisassembler(getTheMSP430Target(),66                                         createMSP430Disassembler);67}68 69static const unsigned GR8DecoderTable[] = {70  MSP430::PCB,  MSP430::SPB,  MSP430::SRB,  MSP430::CGB,71  MSP430::R4B,  MSP430::R5B,  MSP430::R6B,  MSP430::R7B,72  MSP430::R8B,  MSP430::R9B,  MSP430::R10B, MSP430::R11B,73  MSP430::R12B, MSP430::R13B, MSP430::R14B, MSP430::R15B74};75 76static DecodeStatus DecodeGR8RegisterClass(MCInst &MI, uint64_t RegNo,77                                           uint64_t Address,78                                           const MCDisassembler *Decoder) {79  if (RegNo > 15)80    return MCDisassembler::Fail;81 82  unsigned Reg = GR8DecoderTable[RegNo];83  MI.addOperand(MCOperand::createReg(Reg));84  return MCDisassembler::Success;85}86 87static const unsigned GR16DecoderTable[] = {88  MSP430::PC,  MSP430::SP,  MSP430::SR,  MSP430::CG,89  MSP430::R4,  MSP430::R5,  MSP430::R6,  MSP430::R7,90  MSP430::R8,  MSP430::R9,  MSP430::R10, MSP430::R11,91  MSP430::R12, MSP430::R13, MSP430::R14, MSP430::R1592};93 94static DecodeStatus DecodeGR16RegisterClass(MCInst &MI, uint64_t RegNo,95                                            uint64_t Address,96                                            const MCDisassembler *Decoder) {97  if (RegNo > 15)98    return MCDisassembler::Fail;99 100  unsigned Reg = GR16DecoderTable[RegNo];101  MI.addOperand(MCOperand::createReg(Reg));102  return MCDisassembler::Success;103}104 105static DecodeStatus DecodeCGImm(MCInst &MI, uint64_t Bits, uint64_t Address,106                                const MCDisassembler *Decoder) {107  int64_t Imm;108  switch (Bits) {109  default:110    llvm_unreachable("Invalid immediate value");111  case 0x22: Imm =  4; break;112  case 0x32: Imm =  8; break;113  case 0x03: Imm =  0; break;114  case 0x13: Imm =  1; break;115  case 0x23: Imm =  2; break;116  case 0x33: Imm = -1; break;117  }118  MI.addOperand(MCOperand::createImm(Imm));119  return MCDisassembler::Success;120}121 122static DecodeStatus DecodeMemOperand(MCInst &MI, uint64_t Bits,123                                     uint64_t Address,124                                     const MCDisassembler *Decoder) {125  unsigned Reg = Bits & 15;126  unsigned Imm = Bits >> 4;127 128  if (DecodeGR16RegisterClass(MI, Reg, Address, Decoder) !=129      MCDisassembler::Success)130    return MCDisassembler::Fail;131  132  MI.addOperand(MCOperand::createImm((int16_t)Imm));133  return MCDisassembler::Success;134}135 136#include "MSP430GenDisassemblerTables.inc"137 138enum AddrMode {139  amInvalid = 0,140  amRegister,141  amIndexed,142  amIndirect,143  amIndirectPost,144  amSymbolic,145  amImmediate,146  amAbsolute,147  amConstant148};149 150static AddrMode DecodeSrcAddrMode(unsigned Rs, unsigned As) {151  switch (Rs) {152  case 0:153    if (As == 1) return amSymbolic;154    if (As == 2) return amInvalid;155    if (As == 3) return amImmediate;156    break;157  case 2:158    if (As == 1) return amAbsolute;159    if (As == 2) return amConstant;160    if (As == 3) return amConstant;161    break;162  case 3:163    return amConstant;164  default:165    break;166  }167  switch (As) {168  case 0: return amRegister;169  case 1: return amIndexed;170  case 2: return amIndirect;171  case 3: return amIndirectPost;172  default:173    llvm_unreachable("As out of range");174  }175}176 177static AddrMode DecodeSrcAddrModeI(unsigned Insn) {178  unsigned Rs = fieldFromInstruction(Insn, 8, 4);179  unsigned As = fieldFromInstruction(Insn, 4, 2);180  return DecodeSrcAddrMode(Rs, As);181}182 183static AddrMode DecodeSrcAddrModeII(unsigned Insn) {184  unsigned Rs = fieldFromInstruction(Insn, 0, 4);185  unsigned As = fieldFromInstruction(Insn, 4, 2);186  return DecodeSrcAddrMode(Rs, As);187}188 189static AddrMode DecodeDstAddrMode(unsigned Insn) {190  unsigned Rd = fieldFromInstruction(Insn, 0, 4);191  unsigned Ad = fieldFromInstruction(Insn, 7, 1);192  switch (Rd) {193  case 0: return Ad ? amSymbolic : amRegister;194  case 2: return Ad ? amAbsolute : amRegister;195  default:196    break;197  }198  return Ad ? amIndexed : amRegister;199}200 201static const uint8_t *getDecoderTable(AddrMode SrcAM, unsigned Words) {202  assert(0 < Words && Words < 4 && "Incorrect number of words");203  switch (SrcAM) {204  default:205    llvm_unreachable("Invalid addressing mode");206  case amRegister:207    assert(Words < 3 && "Incorrect number of words");208    return Words == 2 ? DecoderTableAlpha32 : DecoderTableAlpha16;209  case amConstant:210    assert(Words < 3 && "Incorrect number of words");211    return Words == 2 ? DecoderTableBeta32 : DecoderTableBeta16;212  case amIndexed:213  case amSymbolic:214  case amImmediate:215  case amAbsolute:216    assert(Words > 1 && "Incorrect number of words");217    return Words == 2 ? DecoderTableGamma32 : DecoderTableGamma48;218  case amIndirect:219  case amIndirectPost:220    assert(Words < 3 && "Incorrect number of words");221    return Words == 2 ? DecoderTableDelta32 : DecoderTableDelta16;222  }223}224 225DecodeStatus MSP430Disassembler::getInstructionI(MCInst &MI, uint64_t &Size,226                                                 ArrayRef<uint8_t> Bytes,227                                                 uint64_t Address,228                                                 raw_ostream &CStream) const {229  uint64_t Insn = support::endian::read16le(Bytes.data());230  AddrMode SrcAM = DecodeSrcAddrModeI(Insn);231  AddrMode DstAM = DecodeDstAddrMode(Insn);232  if (SrcAM == amInvalid || DstAM == amInvalid) {233    Size = 2; // skip one word and let disassembler to try further234    return MCDisassembler::Fail;235  }236 237  unsigned Words = 1;238  switch (SrcAM) {239  case amIndexed:240  case amSymbolic:241  case amImmediate:242  case amAbsolute:243    if (Bytes.size() < (Words + 1) * 2) {244      Size = 2;245      return DecodeStatus::Fail;246    }247    Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16;248    ++Words;249    break;250  default:251    break;252  }253  switch (DstAM) {254  case amIndexed:255  case amSymbolic:256  case amAbsolute:257    if (Bytes.size() < (Words + 1) * 2) {258      Size = 2;259      return DecodeStatus::Fail;260    }261    Insn |= (uint64_t)support::endian::read16le(Bytes.data() + Words * 2)262        << (Words * 16);263    ++Words;264    break;265  default:266    break;267  }268 269  DecodeStatus Result = decodeInstruction(getDecoderTable(SrcAM, Words), MI,270                                          Insn, Address, this, STI);271  if (Result != MCDisassembler::Fail) {272    Size = Words * 2;273    return Result;274  }275 276  Size = 2;277  return DecodeStatus::Fail;278}279 280DecodeStatus MSP430Disassembler::getInstructionII(MCInst &MI, uint64_t &Size,281                                                  ArrayRef<uint8_t> Bytes,282                                                  uint64_t Address,283                                                  raw_ostream &CStream) const {284  uint64_t Insn = support::endian::read16le(Bytes.data());285  AddrMode SrcAM = DecodeSrcAddrModeII(Insn);286  if (SrcAM == amInvalid) {287    Size = 2; // skip one word and let disassembler to try further288    return MCDisassembler::Fail;289  }290 291  unsigned Words = 1;292  switch (SrcAM) {293  case amIndexed:294  case amSymbolic:295  case amImmediate:296  case amAbsolute:297    if (Bytes.size() < (Words + 1) * 2) {298      Size = 2;299      return DecodeStatus::Fail;300    }301    Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16;302    ++Words;303    break;304  default:305    break;306  }307 308  const uint8_t *DecoderTable = Words == 2 ? DecoderTable32 : DecoderTable16;309  DecodeStatus Result = decodeInstruction(DecoderTable, MI, Insn, Address,310                                          this, STI);311  if (Result != MCDisassembler::Fail) {312    Size = Words * 2;313    return Result;314  }315 316  Size = 2;317  return DecodeStatus::Fail;318}319 320static MSP430CC::CondCodes getCondCode(unsigned Cond) {321  switch (Cond) {322  case 0: return MSP430CC::COND_NE;323  case 1: return MSP430CC::COND_E;324  case 2: return MSP430CC::COND_LO;325  case 3: return MSP430CC::COND_HS;326  case 4: return MSP430CC::COND_N;327  case 5: return MSP430CC::COND_GE;328  case 6: return MSP430CC::COND_L;329  case 7: return MSP430CC::COND_NONE;330  default:331    llvm_unreachable("Cond out of range");332  }333}334 335DecodeStatus MSP430Disassembler::getInstructionCJ(MCInst &MI, uint64_t &Size,336                                                  ArrayRef<uint8_t> Bytes,337                                                  uint64_t Address,338                                                  raw_ostream &CStream) const {339  uint64_t Insn = support::endian::read16le(Bytes.data());340  unsigned Cond = fieldFromInstruction(Insn, 10, 3);341  unsigned Offset = fieldFromInstruction(Insn, 0, 10);342 343  MI.addOperand(MCOperand::createImm(SignExtend32(Offset, 10)));344 345  if (Cond == 7)346    MI.setOpcode(MSP430::JMP);347  else {348    MI.setOpcode(MSP430::JCC);349    MI.addOperand(MCOperand::createImm(getCondCode(Cond)));350  }351 352  Size = 2;353  return DecodeStatus::Success;354}355 356DecodeStatus MSP430Disassembler::getInstruction(MCInst &MI, uint64_t &Size,357                                                ArrayRef<uint8_t> Bytes,358                                                uint64_t Address,359                                                raw_ostream &CStream) const {360  if (Bytes.size() < 2) {361    Size = 0;362    return MCDisassembler::Fail;363  }364 365  uint64_t Insn = support::endian::read16le(Bytes.data());366  unsigned Opc = fieldFromInstruction(Insn, 13, 3);367  switch (Opc) {368  case 0:369    return getInstructionII(MI, Size, Bytes, Address, CStream);370  case 1:371    return getInstructionCJ(MI, Size, Bytes, Address, CStream);372  default:373    return getInstructionI(MI, Size, Bytes, Address, CStream);374  }375}376