1 //===-- MSP430Disassembler.cpp - Disassembler for MSP430 ------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the MSP430Disassembler class.
11 //===----------------------------------------------------------------------===//
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"
27 #define DEBUG_TYPE "msp430-disassembler"
29 typedef MCDisassembler::DecodeStatus DecodeStatus
;
32 class MSP430Disassembler
: public MCDisassembler
{
33 DecodeStatus
getInstructionI(MCInst
&MI
, uint64_t &Size
,
34 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
36 raw_ostream
&CStream
) const;
38 DecodeStatus
getInstructionII(MCInst
&MI
, uint64_t &Size
,
39 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
41 raw_ostream
&CStream
) const;
43 DecodeStatus
getInstructionCJ(MCInst
&MI
, uint64_t &Size
,
44 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
46 raw_ostream
&CStream
) const;
49 MSP430Disassembler(const MCSubtargetInfo
&STI
, MCContext
&Ctx
)
50 : MCDisassembler(STI
, Ctx
) {}
52 DecodeStatus
getInstruction(MCInst
&MI
, uint64_t &Size
,
53 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
55 raw_ostream
&CStream
) const override
;
57 } // end anonymous namespace
59 static MCDisassembler
*createMSP430Disassembler(const Target
&T
,
60 const MCSubtargetInfo
&STI
,
62 return new MSP430Disassembler(STI
, Ctx
);
65 extern "C" void LLVMInitializeMSP430Disassembler() {
66 TargetRegistry::RegisterMCDisassembler(getTheMSP430Target(),
67 createMSP430Disassembler
);
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
77 static DecodeStatus
DecodeGR8RegisterClass(MCInst
&MI
, uint64_t RegNo
,
79 const void *Decoder
) {
81 return MCDisassembler::Fail
;
83 unsigned Reg
= GR8DecoderTable
[RegNo
];
84 MI
.addOperand(MCOperand::createReg(Reg
));
85 return MCDisassembler::Success
;
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
95 static DecodeStatus
DecodeGR16RegisterClass(MCInst
&MI
, uint64_t RegNo
,
97 const void *Decoder
) {
99 return MCDisassembler::Fail
;
101 unsigned Reg
= GR16DecoderTable
[RegNo
];
102 MI
.addOperand(MCOperand::createReg(Reg
));
103 return MCDisassembler::Success
;
106 static DecodeStatus
DecodeCGImm(MCInst
&MI
, uint64_t Bits
, uint64_t Address
,
107 const void *Decoder
);
109 static DecodeStatus
DecodeMemOperand(MCInst
&MI
, uint64_t Bits
,
111 const void *Decoder
);
113 #include "MSP430GenDisassemblerTables.inc"
115 static DecodeStatus
DecodeCGImm(MCInst
&MI
, uint64_t Bits
, uint64_t Address
,
116 const void *Decoder
) {
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;
128 MI
.addOperand(MCOperand::createImm(Imm
));
129 return MCDisassembler::Success
;
132 static DecodeStatus
DecodeMemOperand(MCInst
&MI
, uint64_t Bits
,
134 const void *Decoder
) {
135 unsigned Reg
= Bits
& 15;
136 unsigned Imm
= Bits
>> 4;
138 if (DecodeGR16RegisterClass(MI
, Reg
, Address
, Decoder
) !=
139 MCDisassembler::Success
)
140 return MCDisassembler::Fail
;
142 MI
.addOperand(MCOperand::createImm((int16_t)Imm
));
143 return MCDisassembler::Success
;
158 static AddrMode
DecodeSrcAddrMode(unsigned Rs
, unsigned As
) {
161 if (As
== 1) return amSymbolic
;
162 if (As
== 2) return amInvalid
;
163 if (As
== 3) return amImmediate
;
166 if (As
== 1) return amAbsolute
;
167 if (As
== 2) return amConstant
;
168 if (As
== 3) return amConstant
;
176 case 0: return amRegister
;
177 case 1: return amIndexed
;
178 case 2: return amIndirect
;
179 case 3: return amIndirectPost
;
181 llvm_unreachable("As out of range");
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
);
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
);
197 static AddrMode
DecodeDstAddrMode(unsigned Insn
) {
198 unsigned Rd
= fieldFromInstruction(Insn
, 0, 4);
199 unsigned Ad
= fieldFromInstruction(Insn
, 7, 1);
201 case 0: return Ad
? amSymbolic
: amRegister
;
202 case 2: return Ad
? amAbsolute
: amRegister
;
206 return Ad
? amIndexed
: amRegister
;
209 static const uint8_t *getDecoderTable(AddrMode SrcAM
, unsigned Words
) {
210 assert(0 < Words
&& Words
< 4 && "Incorrect number of words");
213 llvm_unreachable("Invalid addressing mode");
215 assert(Words
< 3 && "Incorrect number of words");
216 return Words
== 2 ? DecoderTableAlpha32
: DecoderTableAlpha16
;
218 assert(Words
< 3 && "Incorrect number of words");
219 return Words
== 2 ? DecoderTableBeta32
: DecoderTableBeta16
;
224 assert(Words
> 1 && "Incorrect number of words");
225 return Words
== 2 ? DecoderTableGamma32
: DecoderTableGamma48
;
228 assert(Words
< 3 && "Incorrect number of words");
229 return Words
== 2 ? DecoderTableDelta32
: DecoderTableDelta16
;
233 DecodeStatus
MSP430Disassembler::getInstructionI(MCInst
&MI
, uint64_t &Size
,
234 ArrayRef
<uint8_t> Bytes
,
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
;
252 if (Bytes
.size() < (Words
+ 1) * 2) {
254 return DecodeStatus::Fail
;
256 Insn
|= (uint64_t)support::endian::read16le(Bytes
.data() + 2) << 16;
266 if (Bytes
.size() < (Words
+ 1) * 2) {
268 return DecodeStatus::Fail
;
270 Insn
|= (uint64_t)support::endian::read16le(Bytes
.data() + Words
* 2)
278 DecodeStatus Result
= decodeInstruction(getDecoderTable(SrcAM
, Words
), MI
,
279 Insn
, Address
, this, STI
);
280 if (Result
!= MCDisassembler::Fail
) {
286 return DecodeStatus::Fail
;
289 DecodeStatus
MSP430Disassembler::getInstructionII(MCInst
&MI
, uint64_t &Size
,
290 ArrayRef
<uint8_t> Bytes
,
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
;
307 if (Bytes
.size() < (Words
+ 1) * 2) {
309 return DecodeStatus::Fail
;
311 Insn
|= (uint64_t)support::endian::read16le(Bytes
.data() + 2) << 16;
318 const uint8_t *DecoderTable
= Words
== 2 ? DecoderTable32
: DecoderTable16
;
319 DecodeStatus Result
= decodeInstruction(DecoderTable
, MI
, Insn
, Address
,
321 if (Result
!= MCDisassembler::Fail
) {
327 return DecodeStatus::Fail
;
330 static MSP430CC::CondCodes
getCondCode(unsigned 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
;
341 llvm_unreachable("Cond out of range");
345 DecodeStatus
MSP430Disassembler::getInstructionCJ(MCInst
&MI
, uint64_t &Size
,
346 ArrayRef
<uint8_t> Bytes
,
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);
354 MI
.addOperand(MCOperand::createImm(SignExtend32(Offset
, 10)));
357 MI
.setOpcode(MSP430::JMP
);
359 MI
.setOpcode(MSP430::JCC
);
360 MI
.addOperand(MCOperand::createImm(getCondCode(Cond
)));
364 return DecodeStatus::Success
;
367 DecodeStatus
MSP430Disassembler::getInstruction(MCInst
&MI
, uint64_t &Size
,
368 ArrayRef
<uint8_t> Bytes
,
370 raw_ostream
&VStream
,
371 raw_ostream
&CStream
) const {
372 if (Bytes
.size() < 2) {
374 return MCDisassembler::Fail
;
377 uint64_t Insn
= support::endian::read16le(Bytes
.data());
378 unsigned Opc
= fieldFromInstruction(Insn
, 13, 3);
381 return getInstructionII(MI
, Size
, Bytes
, Address
, VStream
, CStream
);
383 return getInstructionCJ(MI
, Size
, Bytes
, Address
, VStream
, CStream
);
385 return getInstructionI(MI
, Size
, Bytes
, Address
, VStream
, CStream
);