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