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