1 //===- ARCDisassembler.cpp - Disassembler for ARC ---------------*- C++ -*-===//
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 //===----------------------------------------------------------------------===//
10 /// This file is part of the ARC Disassembler.
12 //===----------------------------------------------------------------------===//
15 #include "ARCRegisterInfo.h"
16 #include "MCTargetDesc/ARCMCTargetDesc.h"
17 #include "TargetInfo/ARCTargetInfo.h"
18 #include "llvm/MC/MCContext.h"
19 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
20 #include "llvm/MC/MCFixedLenDisassembler.h"
21 #include "llvm/MC/MCInst.h"
22 #include "llvm/MC/MCInstrInfo.h"
23 #include "llvm/MC/MCSubtargetInfo.h"
24 #include "llvm/Support/TargetRegistry.h"
28 #define DEBUG_TYPE "arc-disassembler"
30 using DecodeStatus
= MCDisassembler::DecodeStatus
;
34 /// A disassembler class for ARC.
35 class ARCDisassembler
: public MCDisassembler
{
37 std::unique_ptr
<MCInstrInfo
const> const MCII
;
39 ARCDisassembler(const MCSubtargetInfo
&STI
, MCContext
&Ctx
,
40 MCInstrInfo
const *MCII
)
41 : MCDisassembler(STI
, Ctx
), MCII(MCII
) {}
43 DecodeStatus
getInstruction(MCInst
&Instr
, uint64_t &Size
,
44 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
45 raw_ostream
&CStream
) const override
;
48 } // end anonymous namespace
50 static bool readInstruction32(ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
51 uint64_t &Size
, uint32_t &Insn
) {
53 // Read 2 16-bit values, but swap hi/lo parts.
55 (Bytes
[0] << 16) | (Bytes
[1] << 24) | (Bytes
[2] << 0) | (Bytes
[3] << 8);
59 static bool readInstruction64(ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
60 uint64_t &Size
, uint64_t &Insn
) {
62 Insn
= ((uint64_t)Bytes
[0] << 16) | ((uint64_t)Bytes
[1] << 24) |
63 ((uint64_t)Bytes
[2] << 0) | ((uint64_t)Bytes
[3] << 8) |
64 ((uint64_t)Bytes
[4] << 48) | ((uint64_t)Bytes
[5] << 56) |
65 ((uint64_t)Bytes
[6] << 32) | ((uint64_t)Bytes
[7] << 40);
69 static bool readInstruction48(ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
70 uint64_t &Size
, uint64_t &Insn
) {
72 Insn
= ((uint64_t)Bytes
[0] << 0) | ((uint64_t)Bytes
[1] << 8) |
73 ((uint64_t)Bytes
[2] << 32) | ((uint64_t)Bytes
[3] << 40) |
74 ((uint64_t)Bytes
[4] << 16) | ((uint64_t)Bytes
[5] << 24);
78 static bool readInstruction16(ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
79 uint64_t &Size
, uint32_t &Insn
) {
81 Insn
= (Bytes
[0] << 0) | (Bytes
[1] << 8);
86 static DecodeStatus
DecodeSignedOperand(MCInst
&Inst
, unsigned InsnS
,
88 const void *Decoder
= nullptr);
91 static DecodeStatus
DecodeFromCyclicRange(MCInst
&Inst
, unsigned InsnS
,
93 const void *Decoder
= nullptr);
96 static DecodeStatus
DecodeBranchTargetS(MCInst
&Inst
, unsigned InsnS
,
97 uint64_t Address
, const void *Decoder
);
99 static DecodeStatus
DecodeMEMrs9(MCInst
&, unsigned, uint64_t, const void *);
101 static DecodeStatus
DecodeLdLImmInstruction(MCInst
&, uint64_t, uint64_t,
104 static DecodeStatus
DecodeStLImmInstruction(MCInst
&, uint64_t, uint64_t,
107 static DecodeStatus
DecodeLdRLImmInstruction(MCInst
&, uint64_t, uint64_t,
110 static DecodeStatus
DecodeCCRU6Instruction(MCInst
&, uint64_t, uint64_t,
113 static DecodeStatus
DecodeMoveHRegInstruction(MCInst
&Inst
, uint64_t, uint64_t,
116 static const uint16_t GPR32DecoderTable
[] = {
117 ARC::R0
, ARC::R1
, ARC::R2
, ARC::R3
, ARC::R4
, ARC::R5
, ARC::R6
,
118 ARC::R7
, ARC::R8
, ARC::R9
, ARC::R10
, ARC::R11
, ARC::R12
, ARC::R13
,
119 ARC::R14
, ARC::R15
, ARC::R16
, ARC::R17
, ARC::R18
, ARC::R19
, ARC::R20
,
120 ARC::R21
, ARC::R22
, ARC::R23
, ARC::R24
, ARC::R25
, ARC::GP
, ARC::FP
,
121 ARC::SP
, ARC::ILINK
, ARC::R30
, ARC::BLINK
};
123 static DecodeStatus
DecodeGPR32RegisterClass(MCInst
&Inst
, unsigned RegNo
,
125 const void *Decoder
) {
127 LLVM_DEBUG(dbgs() << "Not a GPR32 register.");
128 return MCDisassembler::Fail
;
131 unsigned Reg
= GPR32DecoderTable
[RegNo
];
132 Inst
.addOperand(MCOperand::createReg(Reg
));
133 return MCDisassembler::Success
;
136 static DecodeStatus
DecodeGBR32ShortRegister(MCInst
&Inst
, unsigned RegNo
,
138 const void *Decoder
) {
139 // Enumerates registers from ranges [r0-r3],[r12-r15].
141 RegNo
+= 8; // 4 for r12, etc...
143 return DecodeGPR32RegisterClass(Inst
, RegNo
, Address
, Decoder
);
146 #include "ARCGenDisassemblerTables.inc"
148 static unsigned decodeCField(unsigned Insn
) {
149 return fieldFromInstruction(Insn
, 6, 6);
152 static unsigned decodeBField(unsigned Insn
) {
153 return (fieldFromInstruction(Insn
, 12, 3) << 3) |
154 fieldFromInstruction(Insn
, 24, 3);
157 static unsigned decodeAField(unsigned Insn
) {
158 return fieldFromInstruction(Insn
, 0, 6);
161 static DecodeStatus
DecodeMEMrs9(MCInst
&Inst
, unsigned Insn
, uint64_t Address
,
163 // We have the 9-bit immediate in the low bits, 6-bit register in high bits.
164 unsigned S9
= Insn
& 0x1ff;
165 unsigned R
= (Insn
& (0x7fff & ~0x1ff)) >> 9;
166 DecodeGPR32RegisterClass(Inst
, R
, Address
, Dec
);
167 Inst
.addOperand(MCOperand::createImm(SignExtend32
<9>(S9
)));
168 return MCDisassembler::Success
;
171 static bool DecodeSymbolicOperand(MCInst
&Inst
, uint64_t Address
,
172 uint64_t Value
, const void *Decoder
) {
173 static const uint64_t AtLeast
= 2;
174 // TODO: Try to force emitter to use MCDisassembler* instead of void*.
175 auto Disassembler
= static_cast<const MCDisassembler
*>(Decoder
);
176 return (nullptr != Disassembler
&&
177 Disassembler
->tryAddingSymbolicOperand(Inst
, Value
, Address
, true, 0,
181 static void DecodeSymbolicOperandOff(MCInst
&Inst
, uint64_t Address
,
182 uint64_t Offset
, const void *Decoder
) {
183 uint64_t NextAddress
= Address
+ Offset
;
185 if (!DecodeSymbolicOperand(Inst
, Address
, NextAddress
, Decoder
))
186 Inst
.addOperand(MCOperand::createImm(Offset
));
189 template <unsigned B
>
190 static DecodeStatus
DecodeBranchTargetS(MCInst
&Inst
, unsigned InsnS
,
191 uint64_t Address
, const void *Decoder
) {
193 static_assert(B
> 0, "field is empty");
194 DecodeSymbolicOperandOff(Inst
, Address
, SignExtend32
<B
>(InsnS
), Decoder
);
195 return MCDisassembler::Success
;
198 template <unsigned B
>
199 static DecodeStatus
DecodeSignedOperand(MCInst
&Inst
, unsigned InsnS
,
200 uint64_t /*Address*/,
201 const void * /*Decoder*/) {
203 static_assert(B
> 0, "field is empty");
204 Inst
.addOperand(MCOperand::createImm(
205 SignExtend32
<B
>(maskTrailingOnes
<decltype(InsnS
)>(B
) & InsnS
)));
206 return MCDisassembler::Success
;
209 template <unsigned B
>
210 static DecodeStatus
DecodeFromCyclicRange(MCInst
&Inst
, unsigned InsnS
,
211 uint64_t /*Address*/,
212 const void * /*Decoder*/) {
214 static_assert(B
> 0, "field is empty");
215 const unsigned max
= (1u << B
) - 1;
217 MCOperand::createImm(InsnS
< max
? static_cast<int>(InsnS
) : -1));
218 return MCDisassembler::Success
;
221 static DecodeStatus
DecodeStLImmInstruction(MCInst
&Inst
, uint64_t Insn
,
223 const void *Decoder
) {
224 unsigned SrcC
, DstB
, LImm
;
225 DstB
= decodeBField(Insn
);
227 LLVM_DEBUG(dbgs() << "Decoding StLImm found non-limm register.");
228 return MCDisassembler::Fail
;
230 SrcC
= decodeCField(Insn
);
231 DecodeGPR32RegisterClass(Inst
, SrcC
, Address
, Decoder
);
233 Inst
.addOperand(MCOperand::createImm(LImm
));
234 Inst
.addOperand(MCOperand::createImm(0));
235 return MCDisassembler::Success
;
238 static DecodeStatus
DecodeLdLImmInstruction(MCInst
&Inst
, uint64_t Insn
,
240 const void *Decoder
) {
241 unsigned DstA
, SrcB
, LImm
;
242 LLVM_DEBUG(dbgs() << "Decoding LdLImm:\n");
243 SrcB
= decodeBField(Insn
);
245 LLVM_DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");
246 return MCDisassembler::Fail
;
248 DstA
= decodeAField(Insn
);
249 DecodeGPR32RegisterClass(Inst
, DstA
, Address
, Decoder
);
251 Inst
.addOperand(MCOperand::createImm(LImm
));
252 Inst
.addOperand(MCOperand::createImm(0));
253 return MCDisassembler::Success
;
256 static DecodeStatus
DecodeLdRLImmInstruction(MCInst
&Inst
, uint64_t Insn
,
258 const void *Decoder
) {
260 LLVM_DEBUG(dbgs() << "Decoding LdRLimm\n");
261 DstA
= decodeAField(Insn
);
262 DecodeGPR32RegisterClass(Inst
, DstA
, Address
, Decoder
);
263 SrcB
= decodeBField(Insn
);
264 DecodeGPR32RegisterClass(Inst
, SrcB
, Address
, Decoder
);
265 if (decodeCField(Insn
) != 62) {
266 LLVM_DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");
267 return MCDisassembler::Fail
;
269 Inst
.addOperand(MCOperand::createImm((uint32_t)(Insn
>> 32)));
270 return MCDisassembler::Success
;
273 static DecodeStatus
DecodeMoveHRegInstruction(MCInst
&Inst
, uint64_t Insn
,
275 const void *Decoder
) {
276 LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");
277 using Field
= decltype(Insn
);
278 Field H
= fieldFromInstruction(Insn
, 5, 3) |
279 (fieldFromInstruction(Insn
, 0, 2) << 3);
280 Field G
= fieldFromInstruction(Insn
, 8, 3) |
281 (fieldFromInstruction(Insn
, 3, 2) << 3);
283 auto DecodeRegisterOrImm
= [&Inst
, Address
, Decoder
](Field RegNum
,
286 Inst
.addOperand(MCOperand::createImm(Value
));
287 return MCDisassembler::Success
;
290 return DecodeGPR32RegisterClass(Inst
, RegNum
, Address
, Decoder
);
293 if (MCDisassembler::Success
!= DecodeRegisterOrImm(G
, 0))
294 return MCDisassembler::Fail
;
296 return DecodeRegisterOrImm(H
, Insn
>> 16u);
299 static DecodeStatus
DecodeCCRU6Instruction(MCInst
&Inst
, uint64_t Insn
,
301 const void *Decoder
) {
303 LLVM_DEBUG(dbgs() << "Decoding CCRU6 instruction:\n");
304 DstB
= decodeBField(Insn
);
305 DecodeGPR32RegisterClass(Inst
, DstB
, Address
, Decoder
);
306 using Field
= decltype(Insn
);
307 Field U6Field
= fieldFromInstruction(Insn
, 6, 6);
308 Inst
.addOperand(MCOperand::createImm(U6Field
));
309 Field CCField
= fieldFromInstruction(Insn
, 0, 4);
310 Inst
.addOperand(MCOperand::createImm(CCField
));
311 return MCDisassembler::Success
;
314 DecodeStatus
ARCDisassembler::getInstruction(MCInst
&Instr
, uint64_t &Size
,
315 ArrayRef
<uint8_t> Bytes
,
317 raw_ostream
&cStream
) const {
318 MCDisassembler::DecodeStatus Result
;
319 if (Bytes
.size() < 2) {
323 uint8_t DecodeByte
= (Bytes
[1] & 0xF7) >> 3;
324 // 0x00 -> 0x07 are 32-bit instructions.
325 // 0x08 -> 0x1F are 16-bit instructions.
326 if (DecodeByte
< 0x08) {
327 // 32-bit instruction.
328 if (Bytes
.size() < 4) {
329 // Did we decode garbage?
333 if (Bytes
.size() >= 8) {
334 // Attempt to decode 64-bit instruction.
336 if (!readInstruction64(Bytes
, Address
, Size
, Insn64
))
339 decodeInstruction(DecoderTable64
, Instr
, Insn64
, Address
, this, STI
);
340 if (Success
== Result
) {
341 LLVM_DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
344 LLVM_DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
347 if (!readInstruction32(Bytes
, Address
, Size
, Insn32
)) {
350 // Calling the auto-generated decoder function.
351 return decodeInstruction(DecoderTable32
, Instr
, Insn32
, Address
, this, STI
);
353 if (Bytes
.size() >= 6) {
354 // Attempt to treat as instr. with limm data.
356 if (!readInstruction48(Bytes
, Address
, Size
, Insn48
))
359 decodeInstruction(DecoderTable48
, Instr
, Insn48
, Address
, this, STI
);
360 if (Success
== Result
) {
362 dbgs() << "Successfully decoded 16-bit instruction with limm.");
366 dbgs() << "Not a 16-bit instruction with limm, try without it.");
370 if (!readInstruction16(Bytes
, Address
, Size
, Insn16
))
373 // Calling the auto-generated decoder function.
374 return decodeInstruction(DecoderTable16
, Instr
, Insn16
, Address
, this, STI
);
378 static MCDisassembler
*createARCDisassembler(const Target
&T
,
379 const MCSubtargetInfo
&STI
,
381 return new ARCDisassembler(STI
, Ctx
, T
.createMCInstrInfo());
384 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeARCDisassembler() {
385 // Register the disassembler.
386 TargetRegistry::RegisterMCDisassembler(getTheARCTarget(),
387 createARCDisassembler
);