LLVM 20.0.0git
MSP430Disassembler.cpp
Go to the documentation of this file.
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
14#include "MSP430.h"
16#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCInst.h"
22#include "llvm/Support/Endian.h"
23
24using namespace llvm;
25
26#define DEBUG_TYPE "msp430-disassembler"
27
29
30namespace {
31class MSP430Disassembler : public MCDisassembler {
32 DecodeStatus getInstructionI(MCInst &MI, uint64_t &Size,
34 raw_ostream &CStream) const;
35
36 DecodeStatus getInstructionII(MCInst &MI, uint64_t &Size,
38 raw_ostream &CStream) const;
39
40 DecodeStatus getInstructionCJ(MCInst &MI, uint64_t &Size,
42 raw_ostream &CStream) const;
43
44public:
45 MSP430Disassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
46 : MCDisassembler(STI, Ctx) {}
47
50 raw_ostream &CStream) const override;
51};
52} // end anonymous namespace
53
55 const MCSubtargetInfo &STI,
56 MCContext &Ctx) {
57 return new MSP430Disassembler(STI, Ctx);
58}
59
63}
64
65static 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
70};
71
73 uint64_t Address,
74 const MCDisassembler *Decoder) {
75 if (RegNo > 15)
77
78 unsigned Reg = GR8DecoderTable[RegNo];
79 MI.addOperand(MCOperand::createReg(Reg));
81}
82
83static 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
88};
89
91 uint64_t Address,
92 const MCDisassembler *Decoder) {
93 if (RegNo > 15)
95
96 unsigned Reg = GR16DecoderTable[RegNo];
97 MI.addOperand(MCOperand::createReg(Reg));
99}
100
101static DecodeStatus DecodeCGImm(MCInst &MI, uint64_t Bits, uint64_t Address,
102 const MCDisassembler *Decoder);
103
105 uint64_t Address,
106 const MCDisassembler *Decoder);
107
108#include "MSP430GenDisassemblerTables.inc"
109
111 const MCDisassembler *Decoder) {
112 int64_t Imm;
113 switch (Bits) {
114 default:
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;
122 }
123 MI.addOperand(MCOperand::createImm(Imm));
125}
126
128 uint64_t Address,
129 const MCDisassembler *Decoder) {
130 unsigned Reg = Bits & 15;
131 unsigned Imm = Bits >> 4;
132
133 if (DecodeGR16RegisterClass(MI, Reg, Address, Decoder) !=
136
137 MI.addOperand(MCOperand::createImm((int16_t)Imm));
139}
140
152
153static AddrMode DecodeSrcAddrMode(unsigned Rs, unsigned As) {
154 switch (Rs) {
155 case 0:
156 if (As == 1) return amSymbolic;
157 if (As == 2) return amInvalid;
158 if (As == 3) return amImmediate;
159 break;
160 case 2:
161 if (As == 1) return amAbsolute;
162 if (As == 2) return amConstant;
163 if (As == 3) return amConstant;
164 break;
165 case 3:
166 return amConstant;
167 default:
168 break;
169 }
170 switch (As) {
171 case 0: return amRegister;
172 case 1: return amIndexed;
173 case 2: return amIndirect;
174 case 3: return amIndirectPost;
175 default:
176 llvm_unreachable("As out of range");
177 }
178}
179
181 unsigned Rs = fieldFromInstruction(Insn, 8, 4);
182 unsigned As = fieldFromInstruction(Insn, 4, 2);
183 return DecodeSrcAddrMode(Rs, As);
184}
185
187 unsigned Rs = fieldFromInstruction(Insn, 0, 4);
188 unsigned As = fieldFromInstruction(Insn, 4, 2);
189 return DecodeSrcAddrMode(Rs, As);
190}
191
193 unsigned Rd = fieldFromInstruction(Insn, 0, 4);
194 unsigned Ad = fieldFromInstruction(Insn, 7, 1);
195 switch (Rd) {
196 case 0: return Ad ? amSymbolic : amRegister;
197 case 2: return Ad ? amAbsolute : amRegister;
198 default:
199 break;
200 }
201 return Ad ? amIndexed : amRegister;
202}
203
204static const uint8_t *getDecoderTable(AddrMode SrcAM, unsigned Words) {
205 assert(0 < Words && Words < 4 && "Incorrect number of words");
206 switch (SrcAM) {
207 default:
208 llvm_unreachable("Invalid addressing mode");
209 case amRegister:
210 assert(Words < 3 && "Incorrect number of words");
211 return Words == 2 ? DecoderTableAlpha32 : DecoderTableAlpha16;
212 case amConstant:
213 assert(Words < 3 && "Incorrect number of words");
214 return Words == 2 ? DecoderTableBeta32 : DecoderTableBeta16;
215 case amIndexed:
216 case amSymbolic:
217 case amImmediate:
218 case amAbsolute:
219 assert(Words > 1 && "Incorrect number of words");
220 return Words == 2 ? DecoderTableGamma32 : DecoderTableGamma48;
221 case amIndirect:
222 case amIndirectPost:
223 assert(Words < 3 && "Incorrect number of words");
224 return Words == 2 ? DecoderTableDelta32 : DecoderTableDelta16;
225 }
226}
227
228DecodeStatus MSP430Disassembler::getInstructionI(MCInst &MI, uint64_t &Size,
229 ArrayRef<uint8_t> Bytes,
230 uint64_t Address,
231 raw_ostream &CStream) const {
235 if (SrcAM == amInvalid || DstAM == amInvalid) {
236 Size = 2; // skip one word and let disassembler to try further
238 }
239
240 unsigned Words = 1;
241 switch (SrcAM) {
242 case amIndexed:
243 case amSymbolic:
244 case amImmediate:
245 case amAbsolute:
246 if (Bytes.size() < (Words + 1) * 2) {
247 Size = 2;
248 return DecodeStatus::Fail;
249 }
250 Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16;
251 ++Words;
252 break;
253 default:
254 break;
255 }
256 switch (DstAM) {
257 case amIndexed:
258 case amSymbolic:
259 case amAbsolute:
260 if (Bytes.size() < (Words + 1) * 2) {
261 Size = 2;
262 return DecodeStatus::Fail;
263 }
264 Insn |= (uint64_t)support::endian::read16le(Bytes.data() + Words * 2)
265 << (Words * 16);
266 ++Words;
267 break;
268 default:
269 break;
270 }
271
272 DecodeStatus Result = decodeInstruction(getDecoderTable(SrcAM, Words), MI,
273 Insn, Address, this, STI);
274 if (Result != MCDisassembler::Fail) {
275 Size = Words * 2;
276 return Result;
277 }
278
279 Size = 2;
280 return DecodeStatus::Fail;
281}
282
283DecodeStatus MSP430Disassembler::getInstructionII(MCInst &MI, uint64_t &Size,
284 ArrayRef<uint8_t> Bytes,
285 uint64_t Address,
286 raw_ostream &CStream) const {
289 if (SrcAM == amInvalid) {
290 Size = 2; // skip one word and let disassembler to try further
292 }
293
294 unsigned Words = 1;
295 switch (SrcAM) {
296 case amIndexed:
297 case amSymbolic:
298 case amImmediate:
299 case amAbsolute:
300 if (Bytes.size() < (Words + 1) * 2) {
301 Size = 2;
302 return DecodeStatus::Fail;
303 }
304 Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16;
305 ++Words;
306 break;
307 default:
308 break;
309 }
310
311 const uint8_t *DecoderTable = Words == 2 ? DecoderTable32 : DecoderTable16;
312 DecodeStatus Result = decodeInstruction(DecoderTable, MI, Insn, Address,
313 this, STI);
314 if (Result != MCDisassembler::Fail) {
315 Size = Words * 2;
316 return Result;
317 }
318
319 Size = 2;
320 return DecodeStatus::Fail;
321}
322
324 switch (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;
333 default:
334 llvm_unreachable("Cond out of range");
335 }
336}
337
338DecodeStatus MSP430Disassembler::getInstructionCJ(MCInst &MI, uint64_t &Size,
339 ArrayRef<uint8_t> Bytes,
340 uint64_t Address,
341 raw_ostream &CStream) const {
343 unsigned Cond = fieldFromInstruction(Insn, 10, 3);
344 unsigned Offset = fieldFromInstruction(Insn, 0, 10);
345
346 MI.addOperand(MCOperand::createImm(SignExtend32(Offset, 10)));
347
348 if (Cond == 7)
349 MI.setOpcode(MSP430::JMP);
350 else {
351 MI.setOpcode(MSP430::JCC);
353 }
354
355 Size = 2;
356 return DecodeStatus::Success;
357}
358
359DecodeStatus MSP430Disassembler::getInstruction(MCInst &MI, uint64_t &Size,
360 ArrayRef<uint8_t> Bytes,
361 uint64_t Address,
362 raw_ostream &CStream) const {
363 if (Bytes.size() < 2) {
364 Size = 0;
366 }
367
369 unsigned Opc = fieldFromInstruction(Insn, 13, 3);
370 switch (Opc) {
371 case 0:
372 return getInstructionII(MI, Size, Bytes, Address, CStream);
373 case 1:
374 return getInstructionCJ(MI, Size, Bytes, Address, CStream);
375 default:
376 return getInstructionI(MI, Size, Bytes, Address, CStream);
377 }
378}
SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:128
uint64_t Size
IRTranslator LLVM IR MI
MCDisassembler::DecodeStatus DecodeStatus
static DecodeStatus DecodeCGImm(MCInst &MI, uint64_t Bits, uint64_t Address, const MCDisassembler *Decoder)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMSP430Disassembler()
static const unsigned GR16DecoderTable[]
static DecodeStatus DecodeMemOperand(MCInst &MI, uint64_t Bits, uint64_t Address, const MCDisassembler *Decoder)
static AddrMode DecodeSrcAddrModeII(unsigned Insn)
static const uint8_t * getDecoderTable(AddrMode SrcAM, unsigned Words)
static AddrMode DecodeDstAddrMode(unsigned Insn)
static MCDisassembler * createMSP430Disassembler(const Target &T, const MCSubtargetInfo &STI, MCContext &Ctx)
static AddrMode DecodeSrcAddrMode(unsigned Rs, unsigned As)
static AddrMode DecodeSrcAddrModeI(unsigned Insn)
static MSP430CC::CondCodes getCondCode(unsigned Cond)
static const unsigned GR8DecoderTable[]
@ amConstant
@ amIndirect
@ amRegister
@ amSymbolic
@ amImmediate
@ amAbsolute
@ amIndirectPost
static DecodeStatus DecodeGR8RegisterClass(MCInst &MI, uint64_t RegNo, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus DecodeGR16RegisterClass(MCInst &MI, uint64_t RegNo, uint64_t Address, const MCDisassembler *Decoder)
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:168
const T * data() const
Definition: ArrayRef.h:165
Context object for machine code objects.
Definition: MCContext.h:83
Superclass for all disassemblers.
DecodeStatus
Ternary decode status.
virtual DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, ArrayRef< uint8_t > Bytes, uint64_t Address, raw_ostream &CStream) const =0
Returns the disassembly of a single instruction.
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:185
static MCOperand createReg(MCRegister Reg)
Definition: MCInst.h:135
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:142
Generic base class for all target subtargets.
Target - Wrapper for Target specific information.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
CondCodes
Definition: MSP430.h:22
@ COND_LO
Definition: MSP430.h:26
@ COND_N
Definition: MSP430.h:29
@ COND_L
Definition: MSP430.h:28
@ COND_E
Definition: MSP430.h:23
@ COND_GE
Definition: MSP430.h:27
@ COND_NONE
Definition: MSP430.h:30
@ COND_NE
Definition: MSP430.h:24
@ COND_HS
Definition: MSP430.h:25
uint16_t read16le(const void *P)
Definition: Endian.h:422
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
Target & getTheMSP430Target()
constexpr int32_t SignExtend32(uint32_t X)
Sign-extend the number in the bottom B bits of X to a 32-bit integer.
Definition: MathExtras.h:563
static void RegisterMCDisassembler(Target &T, Target::MCDisassemblerCtorTy Fn)
RegisterMCDisassembler - Register a MCDisassembler implementation for the given target.