LLVM  10.0.0svn
MSP430Disassembler.cpp
Go to the documentation of this file.
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"
16 #include "llvm/MC/MCContext.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/Support/Endian.h"
24 
25 using namespace llvm;
26 
27 #define DEBUG_TYPE "msp430-disassembler"
28 
30 
31 namespace {
32 class MSP430Disassembler : public MCDisassembler {
33  DecodeStatus getInstructionI(MCInst &MI, uint64_t &Size,
34  ArrayRef<uint8_t> Bytes, uint64_t Address,
35  raw_ostream &VStream,
36  raw_ostream &CStream) const;
37 
38  DecodeStatus getInstructionII(MCInst &MI, uint64_t &Size,
39  ArrayRef<uint8_t> Bytes, uint64_t Address,
40  raw_ostream &VStream,
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 &VStream,
46  raw_ostream &CStream) const;
47 
48 public:
49  MSP430Disassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
50  : MCDisassembler(STI, Ctx) {}
51 
52  DecodeStatus getInstruction(MCInst &MI, uint64_t &Size,
53  ArrayRef<uint8_t> Bytes, uint64_t Address,
54  raw_ostream &VStream,
55  raw_ostream &CStream) const override;
56 };
57 } // end anonymous namespace
58 
60  const MCSubtargetInfo &STI,
61  MCContext &Ctx) {
62  return new MSP430Disassembler(STI, Ctx);
63 }
64 
68 }
69 
70 static const unsigned GR8DecoderTable[] = {
71  MSP430::PCB, MSP430::SPB, MSP430::SRB, MSP430::CGB,
72  MSP430::FPB, MSP430::R5B, MSP430::R6B, MSP430::R7B,
73  MSP430::R8B, MSP430::R9B, MSP430::R10B, MSP430::R11B,
74  MSP430::R12B, MSP430::R13B, MSP430::R14B, MSP430::R15B
75 };
76 
77 static DecodeStatus DecodeGR8RegisterClass(MCInst &MI, uint64_t RegNo,
78  uint64_t Address,
79  const void *Decoder) {
80  if (RegNo > 15)
81  return MCDisassembler::Fail;
82 
83  unsigned Reg = GR8DecoderTable[RegNo];
86 }
87 
88 static const unsigned GR16DecoderTable[] = {
89  MSP430::PC, MSP430::SP, MSP430::SR, MSP430::CG,
90  MSP430::FP, MSP430::R5, MSP430::R6, MSP430::R7,
91  MSP430::R8, MSP430::R9, MSP430::R10, MSP430::R11,
92  MSP430::R12, MSP430::R13, MSP430::R14, MSP430::R15
93 };
94 
96  uint64_t Address,
97  const void *Decoder) {
98  if (RegNo > 15)
99  return MCDisassembler::Fail;
100 
101  unsigned Reg = GR16DecoderTable[RegNo];
104 }
105 
106 static DecodeStatus DecodeCGImm(MCInst &MI, uint64_t Bits, uint64_t Address,
107  const void *Decoder);
108 
109 static DecodeStatus DecodeMemOperand(MCInst &MI, uint64_t Bits,
110  uint64_t Address,
111  const void *Decoder);
112 
113 #include "MSP430GenDisassemblerTables.inc"
114 
115 static DecodeStatus DecodeCGImm(MCInst &MI, uint64_t Bits, uint64_t Address,
116  const void *Decoder) {
117  int64_t Imm;
118  switch (Bits) {
119  default:
120  llvm_unreachable("Invalid immediate value");
121  case 0x22: Imm = 4; break;
122  case 0x32: Imm = 8; break;
123  case 0x03: Imm = 0; break;
124  case 0x13: Imm = 1; break;
125  case 0x23: Imm = 2; break;
126  case 0x33: Imm = -1; break;
127  }
130 }
131 
133  uint64_t Address,
134  const void *Decoder) {
135  unsigned Reg = Bits & 15;
136  unsigned Imm = Bits >> 4;
137 
138  if (DecodeGR16RegisterClass(MI, Reg, Address, Decoder) !=
140  return MCDisassembler::Fail;
141 
142  MI.addOperand(MCOperand::createImm((int16_t)Imm));
144 }
145 
146 enum AddrMode {
156 };
157 
158 static AddrMode DecodeSrcAddrMode(unsigned Rs, unsigned As) {
159  switch (Rs) {
160  case 0:
161  if (As == 1) return amSymbolic;
162  if (As == 2) return amInvalid;
163  if (As == 3) return amImmediate;
164  break;
165  case 2:
166  if (As == 1) return amAbsolute;
167  if (As == 2) return amConstant;
168  if (As == 3) return amConstant;
169  break;
170  case 3:
171  return amConstant;
172  default:
173  break;
174  }
175  switch (As) {
176  case 0: return amRegister;
177  case 1: return amIndexed;
178  case 2: return amIndirect;
179  case 3: return amIndirectPost;
180  default:
181  llvm_unreachable("As out of range");
182  }
183 }
184 
185 static AddrMode DecodeSrcAddrModeI(unsigned Insn) {
186  unsigned Rs = fieldFromInstruction(Insn, 8, 4);
187  unsigned As = fieldFromInstruction(Insn, 4, 2);
188  return DecodeSrcAddrMode(Rs, As);
189 }
190 
191 static AddrMode DecodeSrcAddrModeII(unsigned Insn) {
192  unsigned Rs = fieldFromInstruction(Insn, 0, 4);
193  unsigned As = fieldFromInstruction(Insn, 4, 2);
194  return DecodeSrcAddrMode(Rs, As);
195 }
196 
197 static AddrMode DecodeDstAddrMode(unsigned Insn) {
198  unsigned Rd = fieldFromInstruction(Insn, 0, 4);
199  unsigned Ad = fieldFromInstruction(Insn, 7, 1);
200  switch (Rd) {
201  case 0: return Ad ? amSymbolic : amRegister;
202  case 2: return Ad ? amAbsolute : amRegister;
203  default:
204  break;
205  }
206  return Ad ? amIndexed : amRegister;
207 }
208 
209 static const uint8_t *getDecoderTable(AddrMode SrcAM, unsigned Words) {
210  assert(0 < Words && Words < 4 && "Incorrect number of words");
211  switch (SrcAM) {
212  default:
213  llvm_unreachable("Invalid addressing mode");
214  case amRegister:
215  assert(Words < 3 && "Incorrect number of words");
216  return Words == 2 ? DecoderTableAlpha32 : DecoderTableAlpha16;
217  case amConstant:
218  assert(Words < 3 && "Incorrect number of words");
219  return Words == 2 ? DecoderTableBeta32 : DecoderTableBeta16;
220  case amIndexed:
221  case amSymbolic:
222  case amImmediate:
223  case amAbsolute:
224  assert(Words > 1 && "Incorrect number of words");
225  return Words == 2 ? DecoderTableGamma32 : DecoderTableGamma48;
226  case amIndirect:
227  case amIndirectPost:
228  assert(Words < 3 && "Incorrect number of words");
229  return Words == 2 ? DecoderTableDelta32 : DecoderTableDelta16;
230  }
231 }
232 
233 DecodeStatus MSP430Disassembler::getInstructionI(MCInst &MI, uint64_t &Size,
234  ArrayRef<uint8_t> Bytes,
235  uint64_t Address,
236  raw_ostream &VStream,
237  raw_ostream &CStream) const {
238  uint64_t Insn = support::endian::read16le(Bytes.data());
239  AddrMode SrcAM = DecodeSrcAddrModeI(Insn);
240  AddrMode DstAM = DecodeDstAddrMode(Insn);
241  if (SrcAM == amInvalid || DstAM == amInvalid) {
242  Size = 2; // skip one word and let disassembler to try further
243  return MCDisassembler::Fail;
244  }
245 
246  unsigned Words = 1;
247  switch (SrcAM) {
248  case amIndexed:
249  case amSymbolic:
250  case amImmediate:
251  case amAbsolute:
252  if (Bytes.size() < (Words + 1) * 2) {
253  Size = 2;
254  return DecodeStatus::Fail;
255  }
256  Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16;
257  ++Words;
258  break;
259  default:
260  break;
261  }
262  switch (DstAM) {
263  case amIndexed:
264  case amSymbolic:
265  case amAbsolute:
266  if (Bytes.size() < (Words + 1) * 2) {
267  Size = 2;
268  return DecodeStatus::Fail;
269  }
270  Insn |= (uint64_t)support::endian::read16le(Bytes.data() + Words * 2)
271  << (Words * 16);
272  ++Words;
273  break;
274  default:
275  break;
276  }
277 
278  DecodeStatus Result = decodeInstruction(getDecoderTable(SrcAM, Words), MI,
279  Insn, Address, this, STI);
280  if (Result != MCDisassembler::Fail) {
281  Size = Words * 2;
282  return Result;
283  }
284 
285  Size = 2;
286  return DecodeStatus::Fail;
287 }
288 
289 DecodeStatus MSP430Disassembler::getInstructionII(MCInst &MI, uint64_t &Size,
290  ArrayRef<uint8_t> Bytes,
291  uint64_t Address,
292  raw_ostream &VStream,
293  raw_ostream &CStream) const {
294  uint64_t Insn = support::endian::read16le(Bytes.data());
295  AddrMode SrcAM = DecodeSrcAddrModeII(Insn);
296  if (SrcAM == amInvalid) {
297  Size = 2; // skip one word and let disassembler to try further
298  return MCDisassembler::Fail;
299  }
300 
301  unsigned Words = 1;
302  switch (SrcAM) {
303  case amIndexed:
304  case amSymbolic:
305  case amImmediate:
306  case amAbsolute:
307  if (Bytes.size() < (Words + 1) * 2) {
308  Size = 2;
309  return DecodeStatus::Fail;
310  }
311  Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16;
312  ++Words;
313  break;
314  default:
315  break;
316  }
317 
318  const uint8_t *DecoderTable = Words == 2 ? DecoderTable32 : DecoderTable16;
319  DecodeStatus Result = decodeInstruction(DecoderTable, MI, Insn, Address,
320  this, STI);
321  if (Result != MCDisassembler::Fail) {
322  Size = Words * 2;
323  return Result;
324  }
325 
326  Size = 2;
327  return DecodeStatus::Fail;
328 }
329 
330 static MSP430CC::CondCodes getCondCode(unsigned Cond) {
331  switch (Cond) {
332  case 0: return MSP430CC::COND_NE;
333  case 1: return MSP430CC::COND_E;
334  case 2: return MSP430CC::COND_LO;
335  case 3: return MSP430CC::COND_HS;
336  case 4: return MSP430CC::COND_N;
337  case 5: return MSP430CC::COND_GE;
338  case 6: return MSP430CC::COND_L;
339  case 7: return MSP430CC::COND_NONE;
340  default:
341  llvm_unreachable("Cond out of range");
342  }
343 }
344 
345 DecodeStatus MSP430Disassembler::getInstructionCJ(MCInst &MI, uint64_t &Size,
346  ArrayRef<uint8_t> Bytes,
347  uint64_t Address,
348  raw_ostream &VStream,
349  raw_ostream &CStream) const {
350  uint64_t Insn = support::endian::read16le(Bytes.data());
351  unsigned Cond = fieldFromInstruction(Insn, 10, 3);
352  unsigned Offset = fieldFromInstruction(Insn, 0, 10);
353 
355 
356  if (Cond == 7)
357  MI.setOpcode(MSP430::JMP);
358  else {
359  MI.setOpcode(MSP430::JCC);
361  }
362 
363  Size = 2;
364  return DecodeStatus::Success;
365 }
366 
367 DecodeStatus MSP430Disassembler::getInstruction(MCInst &MI, uint64_t &Size,
368  ArrayRef<uint8_t> Bytes,
369  uint64_t Address,
370  raw_ostream &VStream,
371  raw_ostream &CStream) const {
372  if (Bytes.size() < 2) {
373  Size = 0;
374  return MCDisassembler::Fail;
375  }
376 
377  uint64_t Insn = support::endian::read16le(Bytes.data());
378  unsigned Opc = fieldFromInstruction(Insn, 13, 3);
379  switch (Opc) {
380  case 0:
381  return getInstructionII(MI, Size, Bytes, Address, VStream, CStream);
382  case 1:
383  return getInstructionCJ(MI, Size, Bytes, Address, VStream, CStream);
384  default:
385  return getInstructionI(MI, Size, Bytes, Address, VStream, CStream);
386  }
387 }
static DecodeStatus DecodeGR16RegisterClass(MCInst &MI, uint64_t RegNo, uint64_t Address, const void *Decoder)
static MSP430CC::CondCodes getCondCode(unsigned Cond)
Target & getTheMSP430Target()
This class represents lattice values for constants.
Definition: AllocatorList.h:23
static DecodeStatus DecodeGR8RegisterClass(MCInst &MI, uint64_t RegNo, uint64_t Address, const void *Decoder)
DecodeStatus
Ternary decode status.
Superclass for all disassemblers.
unsigned Reg
uint16_t read16le(const void *P)
Definition: Endian.h:382
static void RegisterMCDisassembler(Target &T, Target::MCDisassemblerCtorTy Fn)
RegisterMCDisassembler - Register a MCDisassembler implementation for the given target.
void LLVMInitializeMSP430Disassembler()
static DecodeStatus DecodeMemOperand(MCInst &MI, uint64_t Bits, uint64_t Address, const void *Decoder)
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:115
#define Fail
MCDisassembler::DecodeStatus DecodeStatus
Context object for machine code objects.
Definition: MCContext.h:65
static const unsigned GR16DecoderTable[]
int decodeInstruction(InternalInstruction *insn, byteReader_t reader, const void *readerArg, dlog_t logger, void *loggerArg, const void *miiArg, uint64_t startLoc, DisassemblerMode mode)
Decode one instruction and store the decoding results in a buffer provided by the consumer...
static const unsigned GR8DecoderTable[]
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:158
static AddrMode DecodeDstAddrMode(unsigned Insn)
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:148
static AddrMode DecodeSrcAddrMode(unsigned Rs, unsigned As)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const T * data() const
Definition: ArrayRef.h:145
void setOpcode(unsigned Op)
Definition: MCInst.h:170
#define R6(n)
Target - Wrapper for Target specific information.
static AddrMode DecodeSrcAddrModeII(unsigned Insn)
#define Success
static AddrMode DecodeSrcAddrModeI(unsigned Insn)
Generic base class for all target subtargets.
constexpr int32_t SignExtend32(uint32_t X)
Sign-extend the number in the bottom B bits of X to a 32-bit integer.
Definition: MathExtras.h:745
uint32_t Size
Definition: Profile.cpp:46
CondCodes
Definition: MSP430.h:22
static DecodeStatus DecodeCGImm(MCInst &MI, uint64_t Bits, uint64_t Address, const void *Decoder)
static const uint8_t * getDecoderTable(AddrMode SrcAM, unsigned Words)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
IRTranslator LLVM IR MI
void addOperand(const MCOperand &Op)
Definition: MCInst.h:183
static MCDisassembler * createMSP430Disassembler(const Target &T, const MCSubtargetInfo &STI, MCContext &Ctx)
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:122