]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / Target / MSP430 / Disassembler / MSP430Disassembler.cpp
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 "TargetInfo/MSP430TargetInfo.h"
16 #include "llvm/MC/MCContext.h"
17 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
18 #include "llvm/MC/MCFixedLenDisassembler.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCRegisterInfo.h"
21 #include "llvm/MC/MCSubtargetInfo.h"
22 #include "llvm/Support/Endian.h"
23 #include "llvm/Support/TargetRegistry.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 &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
59 static MCDisassembler *createMSP430Disassembler(const Target &T,
60                                                 const MCSubtargetInfo &STI,
61                                                 MCContext &Ctx) {
62   return new MSP430Disassembler(STI, Ctx);
63 }
64
65 extern "C" void LLVMInitializeMSP430Disassembler() {
66   TargetRegistry::RegisterMCDisassembler(getTheMSP430Target(),
67                                          createMSP430Disassembler);
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];
84   MI.addOperand(MCOperand::createReg(Reg));
85   return MCDisassembler::Success;
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
95 static DecodeStatus DecodeGR16RegisterClass(MCInst &MI, uint64_t RegNo,
96                                             uint64_t Address,
97                                             const void *Decoder) {
98   if (RegNo > 15)
99     return MCDisassembler::Fail;
100
101   unsigned Reg = GR16DecoderTable[RegNo];
102   MI.addOperand(MCOperand::createReg(Reg));
103   return MCDisassembler::Success;
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   }
128   MI.addOperand(MCOperand::createImm(Imm));
129   return MCDisassembler::Success;
130 }
131
132 static DecodeStatus DecodeMemOperand(MCInst &MI, uint64_t Bits,
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) !=
139       MCDisassembler::Success)
140     return MCDisassembler::Fail;
141   
142   MI.addOperand(MCOperand::createImm((int16_t)Imm));
143   return MCDisassembler::Success;
144 }
145
146 enum AddrMode {
147   amInvalid = 0,
148   amRegister,
149   amIndexed,
150   amIndirect,
151   amIndirectPost,
152   amSymbolic,
153   amImmediate,
154   amAbsolute,
155   amConstant
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
354   MI.addOperand(MCOperand::createImm(SignExtend32(Offset, 10)));
355
356   if (Cond == 7)
357     MI.setOpcode(MSP430::JMP);
358   else {
359     MI.setOpcode(MSP430::JCC);
360     MI.addOperand(MCOperand::createImm(getCondCode(Cond)));
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 }