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 "llvm/MC/MCContext.h"
16 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
17 #include "llvm/MC/MCFixedLenDisassembler.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCRegisterInfo.h"
20 #include "llvm/MC/MCSubtargetInfo.h"
21 #include "llvm/Support/Endian.h"
22 #include "llvm/Support/TargetRegistry.h"
23 
24 using namespace llvm;
25 
26 #define DEBUG_TYPE "msp430-disassembler"
27 
28 typedef MCDisassembler::DecodeStatus DecodeStatus;
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 
58 static MCDisassembler *createMSP430Disassembler(const Target &T,
59                                                 const MCSubtargetInfo &STI,
60                                                 MCContext &Ctx) {
61   return new MSP430Disassembler(STI, Ctx);
62 }
63 
64 extern "C" void LLVMInitializeMSP430Disassembler() {
65   TargetRegistry::RegisterMCDisassembler(getTheMSP430Target(),
66                                          createMSP430Disassembler);
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];
83   MI.addOperand(MCOperand::createReg(Reg));
84   return MCDisassembler::Success;
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 
94 static DecodeStatus DecodeGR16RegisterClass(MCInst &MI, uint64_t RegNo,
95                                             uint64_t Address,
96                                             const void *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 
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   }
127   MI.addOperand(MCOperand::createImm(Imm));
128   return MCDisassembler::Success;
129 }
130 
131 static DecodeStatus DecodeMemOperand(MCInst &MI, uint64_t Bits,
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) !=
138       MCDisassembler::Success)
139     return MCDisassembler::Fail;
140 
141   MI.addOperand(MCOperand::createImm((int16_t)Imm));
142   return MCDisassembler::Success;
143 }
144 
145 enum AddrMode {
146   amInvalid = 0,
147   amRegister,
148   amIndexed,
149   amIndirect,
150   amIndirectPost,
151   amSymbolic,
152   amImmediate,
153   amAbsolute,
154   amConstant
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 
353   MI.addOperand(MCOperand::createImm(SignExtend32(Offset, 10)));
354 
355   if (Cond == 7)
356     MI.setOpcode(MSP430::JMP);
357   else {
358     MI.setOpcode(MSP430::JCC);
359     MI.addOperand(MCOperand::createImm(getCondCode(Cond)));
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 }
387