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 //===----------------------------------------------------------------------===//
13 #include "MCTargetDesc/MSP430MCTargetDesc.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/Endian.h"
26 #define DEBUG_TYPE "msp430-disassembler"
28 typedef MCDisassembler::DecodeStatus DecodeStatus
;
31 class MSP430Disassembler
: public MCDisassembler
{
32 DecodeStatus
getInstructionI(MCInst
&MI
, uint64_t &Size
,
33 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
34 raw_ostream
&CStream
) const;
36 DecodeStatus
getInstructionII(MCInst
&MI
, uint64_t &Size
,
37 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
38 raw_ostream
&CStream
) const;
40 DecodeStatus
getInstructionCJ(MCInst
&MI
, uint64_t &Size
,
41 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
42 raw_ostream
&CStream
) const;
45 MSP430Disassembler(const MCSubtargetInfo
&STI
, MCContext
&Ctx
)
46 : MCDisassembler(STI
, Ctx
) {}
48 DecodeStatus
getInstruction(MCInst
&MI
, uint64_t &Size
,
49 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
50 raw_ostream
&CStream
) const override
;
52 } // end anonymous namespace
54 static MCDisassembler
*createMSP430Disassembler(const Target
&T
,
55 const MCSubtargetInfo
&STI
,
57 return new MSP430Disassembler(STI
, Ctx
);
60 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeMSP430Disassembler() {
61 TargetRegistry::RegisterMCDisassembler(getTheMSP430Target(),
62 createMSP430Disassembler
);
65 static const unsigned GR8DecoderTable
[] = {
66 MSP430::PCB
, MSP430::SPB
, MSP430::SRB
, MSP430::CGB
,
67 MSP430::R4B
, MSP430::R5B
, MSP430::R6B
, MSP430::R7B
,
68 MSP430::R8B
, MSP430::R9B
, MSP430::R10B
, MSP430::R11B
,
69 MSP430::R12B
, MSP430::R13B
, MSP430::R14B
, MSP430::R15B
72 static DecodeStatus
DecodeGR8RegisterClass(MCInst
&MI
, uint64_t RegNo
,
74 const MCDisassembler
*Decoder
) {
76 return MCDisassembler::Fail
;
78 unsigned Reg
= GR8DecoderTable
[RegNo
];
79 MI
.addOperand(MCOperand::createReg(Reg
));
80 return MCDisassembler::Success
;
83 static const unsigned GR16DecoderTable
[] = {
84 MSP430::PC
, MSP430::SP
, MSP430::SR
, MSP430::CG
,
85 MSP430::R4
, MSP430::R5
, MSP430::R6
, MSP430::R7
,
86 MSP430::R8
, MSP430::R9
, MSP430::R10
, MSP430::R11
,
87 MSP430::R12
, MSP430::R13
, MSP430::R14
, MSP430::R15
90 static DecodeStatus
DecodeGR16RegisterClass(MCInst
&MI
, uint64_t RegNo
,
92 const MCDisassembler
*Decoder
) {
94 return MCDisassembler::Fail
;
96 unsigned Reg
= GR16DecoderTable
[RegNo
];
97 MI
.addOperand(MCOperand::createReg(Reg
));
98 return MCDisassembler::Success
;
101 static DecodeStatus
DecodeCGImm(MCInst
&MI
, uint64_t Bits
, uint64_t Address
,
102 const MCDisassembler
*Decoder
);
104 static DecodeStatus
DecodeMemOperand(MCInst
&MI
, uint64_t Bits
,
106 const MCDisassembler
*Decoder
);
108 #include "MSP430GenDisassemblerTables.inc"
110 static DecodeStatus
DecodeCGImm(MCInst
&MI
, uint64_t Bits
, uint64_t Address
,
111 const MCDisassembler
*Decoder
) {
115 llvm_unreachable("Invalid immediate value");
116 case 0x22: Imm
= 4; break;
117 case 0x32: Imm
= 8; break;
118 case 0x03: Imm
= 0; break;
119 case 0x13: Imm
= 1; break;
120 case 0x23: Imm
= 2; break;
121 case 0x33: Imm
= -1; break;
123 MI
.addOperand(MCOperand::createImm(Imm
));
124 return MCDisassembler::Success
;
127 static DecodeStatus
DecodeMemOperand(MCInst
&MI
, uint64_t Bits
,
129 const MCDisassembler
*Decoder
) {
130 unsigned Reg
= Bits
& 15;
131 unsigned Imm
= Bits
>> 4;
133 if (DecodeGR16RegisterClass(MI
, Reg
, Address
, Decoder
) !=
134 MCDisassembler::Success
)
135 return MCDisassembler::Fail
;
137 MI
.addOperand(MCOperand::createImm((int16_t)Imm
));
138 return MCDisassembler::Success
;
153 static AddrMode
DecodeSrcAddrMode(unsigned Rs
, unsigned As
) {
156 if (As
== 1) return amSymbolic
;
157 if (As
== 2) return amInvalid
;
158 if (As
== 3) return amImmediate
;
161 if (As
== 1) return amAbsolute
;
162 if (As
== 2) return amConstant
;
163 if (As
== 3) return amConstant
;
171 case 0: return amRegister
;
172 case 1: return amIndexed
;
173 case 2: return amIndirect
;
174 case 3: return amIndirectPost
;
176 llvm_unreachable("As out of range");
180 static AddrMode
DecodeSrcAddrModeI(unsigned Insn
) {
181 unsigned Rs
= fieldFromInstruction(Insn
, 8, 4);
182 unsigned As
= fieldFromInstruction(Insn
, 4, 2);
183 return DecodeSrcAddrMode(Rs
, As
);
186 static AddrMode
DecodeSrcAddrModeII(unsigned Insn
) {
187 unsigned Rs
= fieldFromInstruction(Insn
, 0, 4);
188 unsigned As
= fieldFromInstruction(Insn
, 4, 2);
189 return DecodeSrcAddrMode(Rs
, As
);
192 static AddrMode
DecodeDstAddrMode(unsigned Insn
) {
193 unsigned Rd
= fieldFromInstruction(Insn
, 0, 4);
194 unsigned Ad
= fieldFromInstruction(Insn
, 7, 1);
196 case 0: return Ad
? amSymbolic
: amRegister
;
197 case 2: return Ad
? amAbsolute
: amRegister
;
201 return Ad
? amIndexed
: amRegister
;
204 static const uint8_t *getDecoderTable(AddrMode SrcAM
, unsigned Words
) {
205 assert(0 < Words
&& Words
< 4 && "Incorrect number of words");
208 llvm_unreachable("Invalid addressing mode");
210 assert(Words
< 3 && "Incorrect number of words");
211 return Words
== 2 ? DecoderTableAlpha32
: DecoderTableAlpha16
;
213 assert(Words
< 3 && "Incorrect number of words");
214 return Words
== 2 ? DecoderTableBeta32
: DecoderTableBeta16
;
219 assert(Words
> 1 && "Incorrect number of words");
220 return Words
== 2 ? DecoderTableGamma32
: DecoderTableGamma48
;
223 assert(Words
< 3 && "Incorrect number of words");
224 return Words
== 2 ? DecoderTableDelta32
: DecoderTableDelta16
;
228 DecodeStatus
MSP430Disassembler::getInstructionI(MCInst
&MI
, uint64_t &Size
,
229 ArrayRef
<uint8_t> Bytes
,
231 raw_ostream
&CStream
) const {
232 uint64_t Insn
= support::endian::read16le(Bytes
.data());
233 AddrMode SrcAM
= DecodeSrcAddrModeI(Insn
);
234 AddrMode DstAM
= DecodeDstAddrMode(Insn
);
235 if (SrcAM
== amInvalid
|| DstAM
== amInvalid
) {
236 Size
= 2; // skip one word and let disassembler to try further
237 return MCDisassembler::Fail
;
246 if (Bytes
.size() < (Words
+ 1) * 2) {
248 return DecodeStatus::Fail
;
250 Insn
|= (uint64_t)support::endian::read16le(Bytes
.data() + 2) << 16;
260 if (Bytes
.size() < (Words
+ 1) * 2) {
262 return DecodeStatus::Fail
;
264 Insn
|= (uint64_t)support::endian::read16le(Bytes
.data() + Words
* 2)
272 DecodeStatus Result
= decodeInstruction(getDecoderTable(SrcAM
, Words
), MI
,
273 Insn
, Address
, this, STI
);
274 if (Result
!= MCDisassembler::Fail
) {
280 return DecodeStatus::Fail
;
283 DecodeStatus
MSP430Disassembler::getInstructionII(MCInst
&MI
, uint64_t &Size
,
284 ArrayRef
<uint8_t> Bytes
,
286 raw_ostream
&CStream
) const {
287 uint64_t Insn
= support::endian::read16le(Bytes
.data());
288 AddrMode SrcAM
= DecodeSrcAddrModeII(Insn
);
289 if (SrcAM
== amInvalid
) {
290 Size
= 2; // skip one word and let disassembler to try further
291 return MCDisassembler::Fail
;
300 if (Bytes
.size() < (Words
+ 1) * 2) {
302 return DecodeStatus::Fail
;
304 Insn
|= (uint64_t)support::endian::read16le(Bytes
.data() + 2) << 16;
311 const uint8_t *DecoderTable
= Words
== 2 ? DecoderTable32
: DecoderTable16
;
312 DecodeStatus Result
= decodeInstruction(DecoderTable
, MI
, Insn
, Address
,
314 if (Result
!= MCDisassembler::Fail
) {
320 return DecodeStatus::Fail
;
323 static MSP430CC::CondCodes
getCondCode(unsigned Cond
) {
325 case 0: return MSP430CC::COND_NE
;
326 case 1: return MSP430CC::COND_E
;
327 case 2: return MSP430CC::COND_LO
;
328 case 3: return MSP430CC::COND_HS
;
329 case 4: return MSP430CC::COND_N
;
330 case 5: return MSP430CC::COND_GE
;
331 case 6: return MSP430CC::COND_L
;
332 case 7: return MSP430CC::COND_NONE
;
334 llvm_unreachable("Cond out of range");
338 DecodeStatus
MSP430Disassembler::getInstructionCJ(MCInst
&MI
, uint64_t &Size
,
339 ArrayRef
<uint8_t> Bytes
,
341 raw_ostream
&CStream
) const {
342 uint64_t Insn
= support::endian::read16le(Bytes
.data());
343 unsigned Cond
= fieldFromInstruction(Insn
, 10, 3);
344 unsigned Offset
= fieldFromInstruction(Insn
, 0, 10);
346 MI
.addOperand(MCOperand::createImm(SignExtend32(Offset
, 10)));
349 MI
.setOpcode(MSP430::JMP
);
351 MI
.setOpcode(MSP430::JCC
);
352 MI
.addOperand(MCOperand::createImm(getCondCode(Cond
)));
356 return DecodeStatus::Success
;
359 DecodeStatus
MSP430Disassembler::getInstruction(MCInst
&MI
, uint64_t &Size
,
360 ArrayRef
<uint8_t> Bytes
,
362 raw_ostream
&CStream
) const {
363 if (Bytes
.size() < 2) {
365 return MCDisassembler::Fail
;
368 uint64_t Insn
= support::endian::read16le(Bytes
.data());
369 unsigned Opc
= fieldFromInstruction(Insn
, 13, 3);
372 return getInstructionII(MI
, Size
, Bytes
, Address
, CStream
);
374 return getInstructionCJ(MI
, Size
, Bytes
, Address
, CStream
);
376 return getInstructionI(MI
, Size
, Bytes
, Address
, CStream
);