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
,
35 raw_ostream
&CStream
) const;
37 DecodeStatus
getInstructionII(MCInst
&MI
, uint64_t &Size
,
38 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
39 raw_ostream
&CStream
) const;
41 DecodeStatus
getInstructionCJ(MCInst
&MI
, uint64_t &Size
,
42 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
43 raw_ostream
&CStream
) const;
46 MSP430Disassembler(const MCSubtargetInfo
&STI
, MCContext
&Ctx
)
47 : MCDisassembler(STI
, Ctx
) {}
49 DecodeStatus
getInstruction(MCInst
&MI
, uint64_t &Size
,
50 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
51 raw_ostream
&CStream
) const override
;
53 } // end anonymous namespace
55 static MCDisassembler
*createMSP430Disassembler(const Target
&T
,
56 const MCSubtargetInfo
&STI
,
58 return new MSP430Disassembler(STI
, Ctx
);
61 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeMSP430Disassembler() {
62 TargetRegistry::RegisterMCDisassembler(getTheMSP430Target(),
63 createMSP430Disassembler
);
66 static const unsigned GR8DecoderTable
[] = {
67 MSP430::PCB
, MSP430::SPB
, MSP430::SRB
, MSP430::CGB
,
68 MSP430::R4B
, MSP430::R5B
, MSP430::R6B
, MSP430::R7B
,
69 MSP430::R8B
, MSP430::R9B
, MSP430::R10B
, MSP430::R11B
,
70 MSP430::R12B
, MSP430::R13B
, MSP430::R14B
, MSP430::R15B
73 static DecodeStatus
DecodeGR8RegisterClass(MCInst
&MI
, uint64_t RegNo
,
75 const void *Decoder
) {
77 return MCDisassembler::Fail
;
79 unsigned Reg
= GR8DecoderTable
[RegNo
];
80 MI
.addOperand(MCOperand::createReg(Reg
));
81 return MCDisassembler::Success
;
84 static const unsigned GR16DecoderTable
[] = {
85 MSP430::PC
, MSP430::SP
, MSP430::SR
, MSP430::CG
,
86 MSP430::R4
, MSP430::R5
, MSP430::R6
, MSP430::R7
,
87 MSP430::R8
, MSP430::R9
, MSP430::R10
, MSP430::R11
,
88 MSP430::R12
, MSP430::R13
, MSP430::R14
, MSP430::R15
91 static DecodeStatus
DecodeGR16RegisterClass(MCInst
&MI
, uint64_t RegNo
,
93 const void *Decoder
) {
95 return MCDisassembler::Fail
;
97 unsigned Reg
= GR16DecoderTable
[RegNo
];
98 MI
.addOperand(MCOperand::createReg(Reg
));
99 return MCDisassembler::Success
;
102 static DecodeStatus
DecodeCGImm(MCInst
&MI
, uint64_t Bits
, uint64_t Address
,
103 const void *Decoder
);
105 static DecodeStatus
DecodeMemOperand(MCInst
&MI
, uint64_t Bits
,
107 const void *Decoder
);
109 #include "MSP430GenDisassemblerTables.inc"
111 static DecodeStatus
DecodeCGImm(MCInst
&MI
, uint64_t Bits
, uint64_t Address
,
112 const void *Decoder
) {
116 llvm_unreachable("Invalid immediate value");
117 case 0x22: Imm
= 4; break;
118 case 0x32: Imm
= 8; break;
119 case 0x03: Imm
= 0; break;
120 case 0x13: Imm
= 1; break;
121 case 0x23: Imm
= 2; break;
122 case 0x33: Imm
= -1; break;
124 MI
.addOperand(MCOperand::createImm(Imm
));
125 return MCDisassembler::Success
;
128 static DecodeStatus
DecodeMemOperand(MCInst
&MI
, uint64_t Bits
,
130 const void *Decoder
) {
131 unsigned Reg
= Bits
& 15;
132 unsigned Imm
= Bits
>> 4;
134 if (DecodeGR16RegisterClass(MI
, Reg
, Address
, Decoder
) !=
135 MCDisassembler::Success
)
136 return MCDisassembler::Fail
;
138 MI
.addOperand(MCOperand::createImm((int16_t)Imm
));
139 return MCDisassembler::Success
;
154 static AddrMode
DecodeSrcAddrMode(unsigned Rs
, unsigned As
) {
157 if (As
== 1) return amSymbolic
;
158 if (As
== 2) return amInvalid
;
159 if (As
== 3) return amImmediate
;
162 if (As
== 1) return amAbsolute
;
163 if (As
== 2) return amConstant
;
164 if (As
== 3) return amConstant
;
172 case 0: return amRegister
;
173 case 1: return amIndexed
;
174 case 2: return amIndirect
;
175 case 3: return amIndirectPost
;
177 llvm_unreachable("As out of range");
181 static AddrMode
DecodeSrcAddrModeI(unsigned Insn
) {
182 unsigned Rs
= fieldFromInstruction(Insn
, 8, 4);
183 unsigned As
= fieldFromInstruction(Insn
, 4, 2);
184 return DecodeSrcAddrMode(Rs
, As
);
187 static AddrMode
DecodeSrcAddrModeII(unsigned Insn
) {
188 unsigned Rs
= fieldFromInstruction(Insn
, 0, 4);
189 unsigned As
= fieldFromInstruction(Insn
, 4, 2);
190 return DecodeSrcAddrMode(Rs
, As
);
193 static AddrMode
DecodeDstAddrMode(unsigned Insn
) {
194 unsigned Rd
= fieldFromInstruction(Insn
, 0, 4);
195 unsigned Ad
= fieldFromInstruction(Insn
, 7, 1);
197 case 0: return Ad
? amSymbolic
: amRegister
;
198 case 2: return Ad
? amAbsolute
: amRegister
;
202 return Ad
? amIndexed
: amRegister
;
205 static const uint8_t *getDecoderTable(AddrMode SrcAM
, unsigned Words
) {
206 assert(0 < Words
&& Words
< 4 && "Incorrect number of words");
209 llvm_unreachable("Invalid addressing mode");
211 assert(Words
< 3 && "Incorrect number of words");
212 return Words
== 2 ? DecoderTableAlpha32
: DecoderTableAlpha16
;
214 assert(Words
< 3 && "Incorrect number of words");
215 return Words
== 2 ? DecoderTableBeta32
: DecoderTableBeta16
;
220 assert(Words
> 1 && "Incorrect number of words");
221 return Words
== 2 ? DecoderTableGamma32
: DecoderTableGamma48
;
224 assert(Words
< 3 && "Incorrect number of words");
225 return Words
== 2 ? DecoderTableDelta32
: DecoderTableDelta16
;
229 DecodeStatus
MSP430Disassembler::getInstructionI(MCInst
&MI
, uint64_t &Size
,
230 ArrayRef
<uint8_t> Bytes
,
232 raw_ostream
&CStream
) const {
233 uint64_t Insn
= support::endian::read16le(Bytes
.data());
234 AddrMode SrcAM
= DecodeSrcAddrModeI(Insn
);
235 AddrMode DstAM
= DecodeDstAddrMode(Insn
);
236 if (SrcAM
== amInvalid
|| DstAM
== amInvalid
) {
237 Size
= 2; // skip one word and let disassembler to try further
238 return MCDisassembler::Fail
;
247 if (Bytes
.size() < (Words
+ 1) * 2) {
249 return DecodeStatus::Fail
;
251 Insn
|= (uint64_t)support::endian::read16le(Bytes
.data() + 2) << 16;
261 if (Bytes
.size() < (Words
+ 1) * 2) {
263 return DecodeStatus::Fail
;
265 Insn
|= (uint64_t)support::endian::read16le(Bytes
.data() + Words
* 2)
273 DecodeStatus Result
= decodeInstruction(getDecoderTable(SrcAM
, Words
), MI
,
274 Insn
, Address
, this, STI
);
275 if (Result
!= MCDisassembler::Fail
) {
281 return DecodeStatus::Fail
;
284 DecodeStatus
MSP430Disassembler::getInstructionII(MCInst
&MI
, uint64_t &Size
,
285 ArrayRef
<uint8_t> Bytes
,
287 raw_ostream
&CStream
) const {
288 uint64_t Insn
= support::endian::read16le(Bytes
.data());
289 AddrMode SrcAM
= DecodeSrcAddrModeII(Insn
);
290 if (SrcAM
== amInvalid
) {
291 Size
= 2; // skip one word and let disassembler to try further
292 return MCDisassembler::Fail
;
301 if (Bytes
.size() < (Words
+ 1) * 2) {
303 return DecodeStatus::Fail
;
305 Insn
|= (uint64_t)support::endian::read16le(Bytes
.data() + 2) << 16;
312 const uint8_t *DecoderTable
= Words
== 2 ? DecoderTable32
: DecoderTable16
;
313 DecodeStatus Result
= decodeInstruction(DecoderTable
, MI
, Insn
, Address
,
315 if (Result
!= MCDisassembler::Fail
) {
321 return DecodeStatus::Fail
;
324 static MSP430CC::CondCodes
getCondCode(unsigned Cond
) {
326 case 0: return MSP430CC::COND_NE
;
327 case 1: return MSP430CC::COND_E
;
328 case 2: return MSP430CC::COND_LO
;
329 case 3: return MSP430CC::COND_HS
;
330 case 4: return MSP430CC::COND_N
;
331 case 5: return MSP430CC::COND_GE
;
332 case 6: return MSP430CC::COND_L
;
333 case 7: return MSP430CC::COND_NONE
;
335 llvm_unreachable("Cond out of range");
339 DecodeStatus
MSP430Disassembler::getInstructionCJ(MCInst
&MI
, uint64_t &Size
,
340 ArrayRef
<uint8_t> Bytes
,
342 raw_ostream
&CStream
) const {
343 uint64_t Insn
= support::endian::read16le(Bytes
.data());
344 unsigned Cond
= fieldFromInstruction(Insn
, 10, 3);
345 unsigned Offset
= fieldFromInstruction(Insn
, 0, 10);
347 MI
.addOperand(MCOperand::createImm(SignExtend32(Offset
, 10)));
350 MI
.setOpcode(MSP430::JMP
);
352 MI
.setOpcode(MSP430::JCC
);
353 MI
.addOperand(MCOperand::createImm(getCondCode(Cond
)));
357 return DecodeStatus::Success
;
360 DecodeStatus
MSP430Disassembler::getInstruction(MCInst
&MI
, uint64_t &Size
,
361 ArrayRef
<uint8_t> Bytes
,
363 raw_ostream
&CStream
) const {
364 if (Bytes
.size() < 2) {
366 return MCDisassembler::Fail
;
369 uint64_t Insn
= support::endian::read16le(Bytes
.data());
370 unsigned Opc
= fieldFromInstruction(Insn
, 13, 3);
373 return getInstructionII(MI
, Size
, Bytes
, Address
, CStream
);
375 return getInstructionCJ(MI
, Size
, Bytes
, Address
, CStream
);
377 return getInstructionI(MI
, Size
, Bytes
, Address
, CStream
);