blob: 37e3cb6ebf50ca7c1964dd686f05e6b4a2b26b2e [file] [log] [blame]
Anton Korobeynikovf0001f42018-11-15 12:35:04 +00001//===-- MSP430Disassembler.cpp - Disassembler for MSP430 ------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Anton Korobeynikovf0001f42018-11-15 12:35:04 +00006//
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
24using namespace llvm;
25
26#define DEBUG_TYPE "msp430-disassembler"
27
28typedef MCDisassembler::DecodeStatus DecodeStatus;
29
30namespace {
31class 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
47public:
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
58static MCDisassembler *createMSP430Disassembler(const Target &T,
59 const MCSubtargetInfo &STI,
60 MCContext &Ctx) {
61 return new MSP430Disassembler(STI, Ctx);
62}
63
64extern "C" void LLVMInitializeMSP430Disassembler() {
65 TargetRegistry::RegisterMCDisassembler(getTheMSP430Target(),
66 createMSP430Disassembler);
67}
68
69static 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
76static 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
87static 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
94static 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
105static DecodeStatus DecodeCGImm(MCInst &MI, uint64_t Bits, uint64_t Address,
106 const void *Decoder);
107
108static DecodeStatus DecodeMemOperand(MCInst &MI, uint64_t Bits,
109 uint64_t Address,
110 const void *Decoder);
111
112#include "MSP430GenDisassemblerTables.inc"
113
114static 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
131static 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
145enum AddrMode {
146 amInvalid = 0,
147 amRegister,
148 amIndexed,
149 amIndirect,
150 amIndirectPost,
151 amSymbolic,
152 amImmediate,
153 amAbsolute,
154 amConstant
155};
156
157static 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
184static 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
190static 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
196static 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
208static 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
232DecodeStatus 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:
Anton Korobeynikov0681d6b2019-01-10 22:59:50 +0000251 if (Bytes.size() < (Words + 1) * 2) {
252 Size = 2;
253 return DecodeStatus::Fail;
254 }
Anton Korobeynikovf0001f42018-11-15 12:35:04 +0000255 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:
Anton Korobeynikov0681d6b2019-01-10 22:59:50 +0000265 if (Bytes.size() < (Words + 1) * 2) {
266 Size = 2;
267 return DecodeStatus::Fail;
268 }
Anton Korobeynikovf0001f42018-11-15 12:35:04 +0000269 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
288DecodeStatus 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:
Anton Korobeynikov0681d6b2019-01-10 22:59:50 +0000306 if (Bytes.size() < (Words + 1) * 2) {
307 Size = 2;
308 return DecodeStatus::Fail;
309 }
Anton Korobeynikovf0001f42018-11-15 12:35:04 +0000310 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
329static 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
344DecodeStatus 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
366DecodeStatus 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}