LLVM 22.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"
17#include "llvm/MC/MCDecoder.h"
20#include "llvm/MC/MCInst.h"
24#include "llvm/Support/Endian.h"
25
26using namespace llvm;
27using namespace llvm::MCD;
28
29#define DEBUG_TYPE "msp430-disassembler"
30
32
33namespace {
34class MSP430Disassembler : public MCDisassembler {
35 DecodeStatus getInstructionI(MCInst &MI, uint64_t &Size,
36 ArrayRef<uint8_t> Bytes, uint64_t Address,
37 raw_ostream &CStream) const;
38
39 DecodeStatus getInstructionII(MCInst &MI, uint64_t &Size,
40 ArrayRef<uint8_t> Bytes, uint64_t Address,
41 raw_ostream &CStream) const;
42
43 DecodeStatus getInstructionCJ(MCInst &MI, uint64_t &Size,
44 ArrayRef<uint8_t> Bytes, uint64_t Address,
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 &CStream) const override;
54};
55} // end anonymous namespace
56
58 const MCSubtargetInfo &STI,
59 MCContext &Ctx) {
60 return new MSP430Disassembler(STI, Ctx);
61}
62
68
69static const unsigned GR8DecoderTable[] = {
70 MSP430::PCB, MSP430::SPB, MSP430::SRB, MSP430::CGB,
71 MSP430::R4B, 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
77 uint64_t Address,
78 const MCDisassembler *Decoder) {
79 if (RegNo > 15)
81
82 unsigned Reg = GR8DecoderTable[RegNo];
83 MI.addOperand(MCOperand::createReg(Reg));
85}
86
87static const unsigned GR16DecoderTable[] = {
88 MSP430::PC, MSP430::SP, MSP430::SR, MSP430::CG,
89 MSP430::R4, 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
95 uint64_t Address,
96 const MCDisassembler *Decoder) {
97 if (RegNo > 15)
99
100 unsigned Reg = GR16DecoderTable[RegNo];
101 MI.addOperand(MCOperand::createReg(Reg));
103}
104
106 const MCDisassembler *Decoder) {
107 int64_t Imm;
108 switch (Bits) {
109 default:
110 llvm_unreachable("Invalid immediate value");
111 case 0x22: Imm = 4; break;
112 case 0x32: Imm = 8; break;
113 case 0x03: Imm = 0; break;
114 case 0x13: Imm = 1; break;
115 case 0x23: Imm = 2; break;
116 case 0x33: Imm = -1; break;
117 }
118 MI.addOperand(MCOperand::createImm(Imm));
120}
121
123 uint64_t Address,
124 const MCDisassembler *Decoder) {
125 unsigned Reg = Bits & 15;
126 unsigned Imm = Bits >> 4;
127
128 if (DecodeGR16RegisterClass(MI, Reg, Address, Decoder) !=
131
132 MI.addOperand(MCOperand::createImm((int16_t)Imm));
134}
135
136#include "MSP430GenDisassemblerTables.inc"
137
149
150static AddrMode DecodeSrcAddrMode(unsigned Rs, unsigned As) {
151 switch (Rs) {
152 case 0:
153 if (As == 1) return amSymbolic;
154 if (As == 2) return amInvalid;
155 if (As == 3) return amImmediate;
156 break;
157 case 2:
158 if (As == 1) return amAbsolute;
159 if (As == 2) return amConstant;
160 if (As == 3) return amConstant;
161 break;
162 case 3:
163 return amConstant;
164 default:
165 break;
166 }
167 switch (As) {
168 case 0: return amRegister;
169 case 1: return amIndexed;
170 case 2: return amIndirect;
171 case 3: return amIndirectPost;
172 default:
173 llvm_unreachable("As out of range");
174 }
175}
176
177static AddrMode DecodeSrcAddrModeI(unsigned Insn) {
178 unsigned Rs = fieldFromInstruction(Insn, 8, 4);
179 unsigned As = fieldFromInstruction(Insn, 4, 2);
180 return DecodeSrcAddrMode(Rs, As);
181}
182
183static AddrMode DecodeSrcAddrModeII(unsigned Insn) {
184 unsigned Rs = fieldFromInstruction(Insn, 0, 4);
185 unsigned As = fieldFromInstruction(Insn, 4, 2);
186 return DecodeSrcAddrMode(Rs, As);
187}
188
189static AddrMode DecodeDstAddrMode(unsigned Insn) {
190 unsigned Rd = fieldFromInstruction(Insn, 0, 4);
191 unsigned Ad = fieldFromInstruction(Insn, 7, 1);
192 switch (Rd) {
193 case 0: return Ad ? amSymbolic : amRegister;
194 case 2: return Ad ? amAbsolute : amRegister;
195 default:
196 break;
197 }
198 return Ad ? amIndexed : amRegister;
199}
200
201static const uint8_t *getDecoderTable(AddrMode SrcAM, unsigned Words) {
202 assert(0 < Words && Words < 4 && "Incorrect number of words");
203 switch (SrcAM) {
204 default:
205 llvm_unreachable("Invalid addressing mode");
206 case amRegister:
207 assert(Words < 3 && "Incorrect number of words");
208 return Words == 2 ? DecoderTableAlpha32 : DecoderTableAlpha16;
209 case amConstant:
210 assert(Words < 3 && "Incorrect number of words");
211 return Words == 2 ? DecoderTableBeta32 : DecoderTableBeta16;
212 case amIndexed:
213 case amSymbolic:
214 case amImmediate:
215 case amAbsolute:
216 assert(Words > 1 && "Incorrect number of words");
217 return Words == 2 ? DecoderTableGamma32 : DecoderTableGamma48;
218 case amIndirect:
219 case amIndirectPost:
220 assert(Words < 3 && "Incorrect number of words");
221 return Words == 2 ? DecoderTableDelta32 : DecoderTableDelta16;
222 }
223}
224
225DecodeStatus MSP430Disassembler::getInstructionI(MCInst &MI, uint64_t &Size,
226 ArrayRef<uint8_t> Bytes,
227 uint64_t Address,
228 raw_ostream &CStream) const {
229 uint64_t Insn = support::endian::read16le(Bytes.data());
230 AddrMode SrcAM = DecodeSrcAddrModeI(Insn);
231 AddrMode DstAM = DecodeDstAddrMode(Insn);
232 if (SrcAM == amInvalid || DstAM == amInvalid) {
233 Size = 2; // skip one word and let disassembler to try further
235 }
236
237 unsigned Words = 1;
238 switch (SrcAM) {
239 case amIndexed:
240 case amSymbolic:
241 case amImmediate:
242 case amAbsolute:
243 if (Bytes.size() < (Words + 1) * 2) {
244 Size = 2;
245 return DecodeStatus::Fail;
246 }
247 Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16;
248 ++Words;
249 break;
250 default:
251 break;
252 }
253 switch (DstAM) {
254 case amIndexed:
255 case amSymbolic:
256 case amAbsolute:
257 if (Bytes.size() < (Words + 1) * 2) {
258 Size = 2;
259 return DecodeStatus::Fail;
260 }
261 Insn |= (uint64_t)support::endian::read16le(Bytes.data() + Words * 2)
262 << (Words * 16);
263 ++Words;
264 break;
265 default:
266 break;
267 }
268
269 DecodeStatus Result = decodeInstruction(getDecoderTable(SrcAM, Words), MI,
270 Insn, Address, this, STI);
271 if (Result != MCDisassembler::Fail) {
272 Size = Words * 2;
273 return Result;
274 }
275
276 Size = 2;
277 return DecodeStatus::Fail;
278}
279
280DecodeStatus MSP430Disassembler::getInstructionII(MCInst &MI, uint64_t &Size,
281 ArrayRef<uint8_t> Bytes,
282 uint64_t Address,
283 raw_ostream &CStream) const {
284 uint64_t Insn = support::endian::read16le(Bytes.data());
285 AddrMode SrcAM = DecodeSrcAddrModeII(Insn);
286 if (SrcAM == amInvalid) {
287 Size = 2; // skip one word and let disassembler to try further
289 }
290
291 unsigned Words = 1;
292 switch (SrcAM) {
293 case amIndexed:
294 case amSymbolic:
295 case amImmediate:
296 case amAbsolute:
297 if (Bytes.size() < (Words + 1) * 2) {
298 Size = 2;
299 return DecodeStatus::Fail;
300 }
301 Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16;
302 ++Words;
303 break;
304 default:
305 break;
306 }
307
308 const uint8_t *DecoderTable = Words == 2 ? DecoderTable32 : DecoderTable16;
309 DecodeStatus Result = decodeInstruction(DecoderTable, MI, Insn, Address,
310 this, STI);
311 if (Result != MCDisassembler::Fail) {
312 Size = Words * 2;
313 return Result;
314 }
315
316 Size = 2;
317 return DecodeStatus::Fail;
318}
319
321 switch (Cond) {
322 case 0: return MSP430CC::COND_NE;
323 case 1: return MSP430CC::COND_E;
324 case 2: return MSP430CC::COND_LO;
325 case 3: return MSP430CC::COND_HS;
326 case 4: return MSP430CC::COND_N;
327 case 5: return MSP430CC::COND_GE;
328 case 6: return MSP430CC::COND_L;
329 case 7: return MSP430CC::COND_NONE;
330 default:
331 llvm_unreachable("Cond out of range");
332 }
333}
334
335DecodeStatus MSP430Disassembler::getInstructionCJ(MCInst &MI, uint64_t &Size,
336 ArrayRef<uint8_t> Bytes,
337 uint64_t Address,
338 raw_ostream &CStream) const {
339 uint64_t Insn = support::endian::read16le(Bytes.data());
340 unsigned Cond = fieldFromInstruction(Insn, 10, 3);
341 unsigned Offset = fieldFromInstruction(Insn, 0, 10);
342
343 MI.addOperand(MCOperand::createImm(SignExtend32(Offset, 10)));
344
345 if (Cond == 7)
346 MI.setOpcode(MSP430::JMP);
347 else {
348 MI.setOpcode(MSP430::JCC);
350 }
351
352 Size = 2;
353 return DecodeStatus::Success;
354}
355
356DecodeStatus MSP430Disassembler::getInstruction(MCInst &MI, uint64_t &Size,
357 ArrayRef<uint8_t> Bytes,
358 uint64_t Address,
359 raw_ostream &CStream) const {
360 if (Bytes.size() < 2) {
361 Size = 0;
363 }
364
365 uint64_t Insn = support::endian::read16le(Bytes.data());
366 unsigned Opc = fieldFromInstruction(Insn, 13, 3);
367 switch (Opc) {
368 case 0:
369 return getInstructionII(MI, Size, Bytes, Address, CStream);
370 case 1:
371 return getInstructionCJ(MI, Size, Bytes, Address, CStream);
372 default:
373 return getInstructionI(MI, Size, Bytes, Address, CStream);
374 }
375}
MCDisassembler::DecodeStatus DecodeStatus
static SDValue getCondCode(SelectionDAG &DAG, AArch64CC::CondCode CC)
Like SelectionDAG::getCondCode(), but for AArch64 condition codes.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const uint8_t * getDecoderTable(uint64_t Size)
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
IRTranslator LLVM IR MI
static DecodeStatus DecodeCGImm(MCInst &MI, uint64_t Bits, uint64_t Address, const MCDisassembler *Decoder)
static const unsigned GR16DecoderTable[]
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMSP430Disassembler()
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 const unsigned GR8DecoderTable[]
@ 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)
Register Reg
#define T
const SmallVectorImpl< MachineOperand > & Cond
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:147
const T * data() const
Definition ArrayRef.h:144
Context object for machine code objects.
Definition MCContext.h:83
Superclass for all disassemblers.
DecodeStatus
Ternary decode status.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
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:53
#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
std::enable_if_t< std::is_integral_v< IntType >, IntType > fieldFromInstruction(const IntType &Insn, unsigned StartBit, unsigned NumBits)
Definition MCDecoder.h:37
uint16_t read16le(const void *P)
Definition Endian.h:425
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
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:565
static void RegisterMCDisassembler(Target &T, Target::MCDisassemblerCtorTy Fn)
RegisterMCDisassembler - Register a MCDisassembler implementation for the given target.