Path: blob/main/contrib/llvm-project/llvm/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp
35293 views
//===-- MSP430Disassembler.cpp - Disassembler for MSP430 ------------------===//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// This file implements the MSP430Disassembler class.9//10//===----------------------------------------------------------------------===//1112#include "MCTargetDesc/MSP430MCTargetDesc.h"13#include "MSP430.h"14#include "TargetInfo/MSP430TargetInfo.h"15#include "llvm/MC/MCContext.h"16#include "llvm/MC/MCDecoderOps.h"17#include "llvm/MC/MCDisassembler/MCDisassembler.h"18#include "llvm/MC/MCInst.h"19#include "llvm/MC/MCRegisterInfo.h"20#include "llvm/MC/MCSubtargetInfo.h"21#include "llvm/MC/TargetRegistry.h"22#include "llvm/Support/Endian.h"2324using namespace llvm;2526#define DEBUG_TYPE "msp430-disassembler"2728typedef MCDisassembler::DecodeStatus DecodeStatus;2930namespace {31class MSP430Disassembler : public MCDisassembler {32DecodeStatus getInstructionI(MCInst &MI, uint64_t &Size,33ArrayRef<uint8_t> Bytes, uint64_t Address,34raw_ostream &CStream) const;3536DecodeStatus getInstructionII(MCInst &MI, uint64_t &Size,37ArrayRef<uint8_t> Bytes, uint64_t Address,38raw_ostream &CStream) const;3940DecodeStatus getInstructionCJ(MCInst &MI, uint64_t &Size,41ArrayRef<uint8_t> Bytes, uint64_t Address,42raw_ostream &CStream) const;4344public:45MSP430Disassembler(const MCSubtargetInfo &STI, MCContext &Ctx)46: MCDisassembler(STI, Ctx) {}4748DecodeStatus getInstruction(MCInst &MI, uint64_t &Size,49ArrayRef<uint8_t> Bytes, uint64_t Address,50raw_ostream &CStream) const override;51};52} // end anonymous namespace5354static MCDisassembler *createMSP430Disassembler(const Target &T,55const MCSubtargetInfo &STI,56MCContext &Ctx) {57return new MSP430Disassembler(STI, Ctx);58}5960extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMSP430Disassembler() {61TargetRegistry::RegisterMCDisassembler(getTheMSP430Target(),62createMSP430Disassembler);63}6465static const unsigned GR8DecoderTable[] = {66MSP430::PCB, MSP430::SPB, MSP430::SRB, MSP430::CGB,67MSP430::R4B, MSP430::R5B, MSP430::R6B, MSP430::R7B,68MSP430::R8B, MSP430::R9B, MSP430::R10B, MSP430::R11B,69MSP430::R12B, MSP430::R13B, MSP430::R14B, MSP430::R15B70};7172static DecodeStatus DecodeGR8RegisterClass(MCInst &MI, uint64_t RegNo,73uint64_t Address,74const MCDisassembler *Decoder) {75if (RegNo > 15)76return MCDisassembler::Fail;7778unsigned Reg = GR8DecoderTable[RegNo];79MI.addOperand(MCOperand::createReg(Reg));80return MCDisassembler::Success;81}8283static const unsigned GR16DecoderTable[] = {84MSP430::PC, MSP430::SP, MSP430::SR, MSP430::CG,85MSP430::R4, MSP430::R5, MSP430::R6, MSP430::R7,86MSP430::R8, MSP430::R9, MSP430::R10, MSP430::R11,87MSP430::R12, MSP430::R13, MSP430::R14, MSP430::R1588};8990static DecodeStatus DecodeGR16RegisterClass(MCInst &MI, uint64_t RegNo,91uint64_t Address,92const MCDisassembler *Decoder) {93if (RegNo > 15)94return MCDisassembler::Fail;9596unsigned Reg = GR16DecoderTable[RegNo];97MI.addOperand(MCOperand::createReg(Reg));98return MCDisassembler::Success;99}100101static DecodeStatus DecodeCGImm(MCInst &MI, uint64_t Bits, uint64_t Address,102const MCDisassembler *Decoder);103104static DecodeStatus DecodeMemOperand(MCInst &MI, uint64_t Bits,105uint64_t Address,106const MCDisassembler *Decoder);107108#include "MSP430GenDisassemblerTables.inc"109110static DecodeStatus DecodeCGImm(MCInst &MI, uint64_t Bits, uint64_t Address,111const MCDisassembler *Decoder) {112int64_t Imm;113switch (Bits) {114default:115llvm_unreachable("Invalid immediate value");116case 0x22: Imm = 4; break;117case 0x32: Imm = 8; break;118case 0x03: Imm = 0; break;119case 0x13: Imm = 1; break;120case 0x23: Imm = 2; break;121case 0x33: Imm = -1; break;122}123MI.addOperand(MCOperand::createImm(Imm));124return MCDisassembler::Success;125}126127static DecodeStatus DecodeMemOperand(MCInst &MI, uint64_t Bits,128uint64_t Address,129const MCDisassembler *Decoder) {130unsigned Reg = Bits & 15;131unsigned Imm = Bits >> 4;132133if (DecodeGR16RegisterClass(MI, Reg, Address, Decoder) !=134MCDisassembler::Success)135return MCDisassembler::Fail;136137MI.addOperand(MCOperand::createImm((int16_t)Imm));138return MCDisassembler::Success;139}140141enum AddrMode {142amInvalid = 0,143amRegister,144amIndexed,145amIndirect,146amIndirectPost,147amSymbolic,148amImmediate,149amAbsolute,150amConstant151};152153static AddrMode DecodeSrcAddrMode(unsigned Rs, unsigned As) {154switch (Rs) {155case 0:156if (As == 1) return amSymbolic;157if (As == 2) return amInvalid;158if (As == 3) return amImmediate;159break;160case 2:161if (As == 1) return amAbsolute;162if (As == 2) return amConstant;163if (As == 3) return amConstant;164break;165case 3:166return amConstant;167default:168break;169}170switch (As) {171case 0: return amRegister;172case 1: return amIndexed;173case 2: return amIndirect;174case 3: return amIndirectPost;175default:176llvm_unreachable("As out of range");177}178}179180static AddrMode DecodeSrcAddrModeI(unsigned Insn) {181unsigned Rs = fieldFromInstruction(Insn, 8, 4);182unsigned As = fieldFromInstruction(Insn, 4, 2);183return DecodeSrcAddrMode(Rs, As);184}185186static AddrMode DecodeSrcAddrModeII(unsigned Insn) {187unsigned Rs = fieldFromInstruction(Insn, 0, 4);188unsigned As = fieldFromInstruction(Insn, 4, 2);189return DecodeSrcAddrMode(Rs, As);190}191192static AddrMode DecodeDstAddrMode(unsigned Insn) {193unsigned Rd = fieldFromInstruction(Insn, 0, 4);194unsigned Ad = fieldFromInstruction(Insn, 7, 1);195switch (Rd) {196case 0: return Ad ? amSymbolic : amRegister;197case 2: return Ad ? amAbsolute : amRegister;198default:199break;200}201return Ad ? amIndexed : amRegister;202}203204static const uint8_t *getDecoderTable(AddrMode SrcAM, unsigned Words) {205assert(0 < Words && Words < 4 && "Incorrect number of words");206switch (SrcAM) {207default:208llvm_unreachable("Invalid addressing mode");209case amRegister:210assert(Words < 3 && "Incorrect number of words");211return Words == 2 ? DecoderTableAlpha32 : DecoderTableAlpha16;212case amConstant:213assert(Words < 3 && "Incorrect number of words");214return Words == 2 ? DecoderTableBeta32 : DecoderTableBeta16;215case amIndexed:216case amSymbolic:217case amImmediate:218case amAbsolute:219assert(Words > 1 && "Incorrect number of words");220return Words == 2 ? DecoderTableGamma32 : DecoderTableGamma48;221case amIndirect:222case amIndirectPost:223assert(Words < 3 && "Incorrect number of words");224return Words == 2 ? DecoderTableDelta32 : DecoderTableDelta16;225}226}227228DecodeStatus MSP430Disassembler::getInstructionI(MCInst &MI, uint64_t &Size,229ArrayRef<uint8_t> Bytes,230uint64_t Address,231raw_ostream &CStream) const {232uint64_t Insn = support::endian::read16le(Bytes.data());233AddrMode SrcAM = DecodeSrcAddrModeI(Insn);234AddrMode DstAM = DecodeDstAddrMode(Insn);235if (SrcAM == amInvalid || DstAM == amInvalid) {236Size = 2; // skip one word and let disassembler to try further237return MCDisassembler::Fail;238}239240unsigned Words = 1;241switch (SrcAM) {242case amIndexed:243case amSymbolic:244case amImmediate:245case amAbsolute:246if (Bytes.size() < (Words + 1) * 2) {247Size = 2;248return DecodeStatus::Fail;249}250Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16;251++Words;252break;253default:254break;255}256switch (DstAM) {257case amIndexed:258case amSymbolic:259case amAbsolute:260if (Bytes.size() < (Words + 1) * 2) {261Size = 2;262return DecodeStatus::Fail;263}264Insn |= (uint64_t)support::endian::read16le(Bytes.data() + Words * 2)265<< (Words * 16);266++Words;267break;268default:269break;270}271272DecodeStatus Result = decodeInstruction(getDecoderTable(SrcAM, Words), MI,273Insn, Address, this, STI);274if (Result != MCDisassembler::Fail) {275Size = Words * 2;276return Result;277}278279Size = 2;280return DecodeStatus::Fail;281}282283DecodeStatus MSP430Disassembler::getInstructionII(MCInst &MI, uint64_t &Size,284ArrayRef<uint8_t> Bytes,285uint64_t Address,286raw_ostream &CStream) const {287uint64_t Insn = support::endian::read16le(Bytes.data());288AddrMode SrcAM = DecodeSrcAddrModeII(Insn);289if (SrcAM == amInvalid) {290Size = 2; // skip one word and let disassembler to try further291return MCDisassembler::Fail;292}293294unsigned Words = 1;295switch (SrcAM) {296case amIndexed:297case amSymbolic:298case amImmediate:299case amAbsolute:300if (Bytes.size() < (Words + 1) * 2) {301Size = 2;302return DecodeStatus::Fail;303}304Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16;305++Words;306break;307default:308break;309}310311const uint8_t *DecoderTable = Words == 2 ? DecoderTable32 : DecoderTable16;312DecodeStatus Result = decodeInstruction(DecoderTable, MI, Insn, Address,313this, STI);314if (Result != MCDisassembler::Fail) {315Size = Words * 2;316return Result;317}318319Size = 2;320return DecodeStatus::Fail;321}322323static MSP430CC::CondCodes getCondCode(unsigned Cond) {324switch (Cond) {325case 0: return MSP430CC::COND_NE;326case 1: return MSP430CC::COND_E;327case 2: return MSP430CC::COND_LO;328case 3: return MSP430CC::COND_HS;329case 4: return MSP430CC::COND_N;330case 5: return MSP430CC::COND_GE;331case 6: return MSP430CC::COND_L;332case 7: return MSP430CC::COND_NONE;333default:334llvm_unreachable("Cond out of range");335}336}337338DecodeStatus MSP430Disassembler::getInstructionCJ(MCInst &MI, uint64_t &Size,339ArrayRef<uint8_t> Bytes,340uint64_t Address,341raw_ostream &CStream) const {342uint64_t Insn = support::endian::read16le(Bytes.data());343unsigned Cond = fieldFromInstruction(Insn, 10, 3);344unsigned Offset = fieldFromInstruction(Insn, 0, 10);345346MI.addOperand(MCOperand::createImm(SignExtend32(Offset, 10)));347348if (Cond == 7)349MI.setOpcode(MSP430::JMP);350else {351MI.setOpcode(MSP430::JCC);352MI.addOperand(MCOperand::createImm(getCondCode(Cond)));353}354355Size = 2;356return DecodeStatus::Success;357}358359DecodeStatus MSP430Disassembler::getInstruction(MCInst &MI, uint64_t &Size,360ArrayRef<uint8_t> Bytes,361uint64_t Address,362raw_ostream &CStream) const {363if (Bytes.size() < 2) {364Size = 0;365return MCDisassembler::Fail;366}367368uint64_t Insn = support::endian::read16le(Bytes.data());369unsigned Opc = fieldFromInstruction(Insn, 13, 3);370switch (Opc) {371case 0:372return getInstructionII(MI, Size, Bytes, Address, CStream);373case 1:374return getInstructionCJ(MI, Size, Bytes, Address, CStream);375default:376return getInstructionI(MI, Size, Bytes, Address, CStream);377}378}379380381