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