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