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