Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
35293 views
1
//===- ARCDisassembler.cpp - Disassembler for ARC ---------------*- C++ -*-===//
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
/// \file
10
/// This file is part of the ARC Disassembler.
11
///
12
//===----------------------------------------------------------------------===//
13
14
#include "ARC.h"
15
#include "ARCRegisterInfo.h"
16
#include "MCTargetDesc/ARCMCTargetDesc.h"
17
#include "TargetInfo/ARCTargetInfo.h"
18
#include "llvm/MC/MCContext.h"
19
#include "llvm/MC/MCDecoderOps.h"
20
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
21
#include "llvm/MC/MCInst.h"
22
#include "llvm/MC/MCInstrInfo.h"
23
#include "llvm/MC/MCSubtargetInfo.h"
24
#include "llvm/MC/TargetRegistry.h"
25
26
using namespace llvm;
27
28
#define DEBUG_TYPE "arc-disassembler"
29
30
using DecodeStatus = MCDisassembler::DecodeStatus;
31
32
namespace {
33
34
/// A disassembler class for ARC.
35
class ARCDisassembler : public MCDisassembler {
36
public:
37
std::unique_ptr<MCInstrInfo const> const MCII;
38
39
ARCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
40
MCInstrInfo const *MCII)
41
: MCDisassembler(STI, Ctx), MCII(MCII) {}
42
43
DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
44
ArrayRef<uint8_t> Bytes, uint64_t Address,
45
raw_ostream &CStream) const override;
46
};
47
48
} // end anonymous namespace
49
50
static bool readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
51
uint64_t &Size, uint32_t &Insn) {
52
Size = 4;
53
// Read 2 16-bit values, but swap hi/lo parts.
54
Insn =
55
(Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
56
return true;
57
}
58
59
static bool readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,
60
uint64_t &Size, uint64_t &Insn) {
61
Size = 8;
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);
66
return true;
67
}
68
69
static bool readInstruction48(ArrayRef<uint8_t> Bytes, uint64_t Address,
70
uint64_t &Size, uint64_t &Insn) {
71
Size = 6;
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);
75
return true;
76
}
77
78
static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
79
uint64_t &Size, uint32_t &Insn) {
80
Size = 2;
81
Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
82
return true;
83
}
84
85
template <unsigned B>
86
static DecodeStatus
87
DecodeSignedOperand(MCInst &Inst, unsigned InsnS, uint64_t Address = 0,
88
const MCDisassembler *Decoder = nullptr);
89
90
template <unsigned B>
91
static DecodeStatus
92
DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS, uint64_t Address = 0,
93
const MCDisassembler *Decoder = nullptr);
94
95
template <unsigned B>
96
static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
97
uint64_t Address,
98
const MCDisassembler *Decoder);
99
100
static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t,
101
const MCDisassembler *);
102
103
static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t,
104
const MCDisassembler *);
105
106
static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,
107
const MCDisassembler *);
108
109
static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,
110
const MCDisassembler *);
111
112
static DecodeStatus DecodeSOPwithRS12(MCInst &, uint64_t, uint64_t,
113
const MCDisassembler *);
114
115
static DecodeStatus DecodeSOPwithRU6(MCInst &, uint64_t, uint64_t,
116
const MCDisassembler *);
117
118
static DecodeStatus DecodeCCRU6Instruction(MCInst &, uint64_t, uint64_t,
119
const MCDisassembler *);
120
121
static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,
122
const MCDisassembler *);
123
124
static const uint16_t GPR32DecoderTable[] = {
125
ARC::R0, ARC::R1, ARC::R2, ARC::R3, ARC::R4, ARC::R5, ARC::R6,
126
ARC::R7, ARC::R8, ARC::R9, ARC::R10, ARC::R11, ARC::R12, ARC::R13,
127
ARC::R14, ARC::R15, ARC::R16, ARC::R17, ARC::R18, ARC::R19, ARC::R20,
128
ARC::R21, ARC::R22, ARC::R23, ARC::R24, ARC::R25, ARC::GP, ARC::FP,
129
ARC::SP, ARC::ILINK, ARC::R30, ARC::BLINK};
130
131
static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
132
uint64_t Address,
133
const MCDisassembler *Decoder) {
134
if (RegNo >= 32) {
135
LLVM_DEBUG(dbgs() << "Not a GPR32 register.");
136
return MCDisassembler::Fail;
137
}
138
139
unsigned Reg = GPR32DecoderTable[RegNo];
140
Inst.addOperand(MCOperand::createReg(Reg));
141
return MCDisassembler::Success;
142
}
143
144
static DecodeStatus DecodeGBR32ShortRegister(MCInst &Inst, unsigned RegNo,
145
uint64_t Address,
146
const MCDisassembler *Decoder) {
147
// Enumerates registers from ranges [r0-r3],[r12-r15].
148
if (RegNo > 3)
149
RegNo += 8; // 4 for r12, etc...
150
151
return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
152
}
153
154
#include "ARCGenDisassemblerTables.inc"
155
156
static unsigned decodeCField(unsigned Insn) {
157
return fieldFromInstruction(Insn, 6, 6);
158
}
159
160
static unsigned decodeBField(unsigned Insn) {
161
return (fieldFromInstruction(Insn, 12, 3) << 3) |
162
fieldFromInstruction(Insn, 24, 3);
163
}
164
165
static unsigned decodeAField(unsigned Insn) {
166
return fieldFromInstruction(Insn, 0, 6);
167
}
168
169
static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,
170
const MCDisassembler *Dec) {
171
// We have the 9-bit immediate in the low bits, 6-bit register in high bits.
172
unsigned S9 = Insn & 0x1ff;
173
unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
174
DecodeGPR32RegisterClass(Inst, R, Address, Dec);
175
Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9)));
176
return MCDisassembler::Success;
177
}
178
179
static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,
180
uint64_t Value,
181
const MCDisassembler *Decoder) {
182
static const uint64_t AtLeast = 2;
183
return (nullptr != Decoder && Decoder->tryAddingSymbolicOperand(
184
Inst, Value, Address, true, 0, AtLeast, 0));
185
}
186
187
static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,
188
uint64_t Offset,
189
const MCDisassembler *Decoder) {
190
uint64_t NextAddress = Address + Offset;
191
192
if (!DecodeSymbolicOperand(Inst, Address, NextAddress, Decoder))
193
Inst.addOperand(MCOperand::createImm(Offset));
194
}
195
196
template <unsigned B>
197
static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
198
uint64_t Address,
199
const MCDisassembler *Decoder) {
200
201
static_assert(B > 0, "field is empty");
202
DecodeSymbolicOperandOff(Inst, Address, SignExtend32<B>(InsnS), Decoder);
203
return MCDisassembler::Success;
204
}
205
206
template <unsigned B>
207
static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
208
uint64_t /*Address*/,
209
const MCDisassembler * /*Decoder*/) {
210
211
static_assert(B > 0, "field is empty");
212
Inst.addOperand(MCOperand::createImm(
213
SignExtend32<B>(maskTrailingOnes<decltype(InsnS)>(B) & InsnS)));
214
return MCDisassembler::Success;
215
}
216
217
template <unsigned B>
218
static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
219
uint64_t /*Address*/,
220
const MCDisassembler * /*Decoder*/) {
221
222
static_assert(B > 0, "field is empty");
223
const unsigned max = (1u << B) - 1;
224
Inst.addOperand(
225
MCOperand::createImm(InsnS < max ? static_cast<int>(InsnS) : -1));
226
return MCDisassembler::Success;
227
}
228
229
static DecodeStatus DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn,
230
uint64_t Address,
231
const MCDisassembler *Decoder) {
232
unsigned SrcC, DstB, LImm;
233
DstB = decodeBField(Insn);
234
if (DstB != 62) {
235
LLVM_DEBUG(dbgs() << "Decoding StLImm found non-limm register.");
236
return MCDisassembler::Fail;
237
}
238
SrcC = decodeCField(Insn);
239
DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);
240
LImm = (Insn >> 32);
241
Inst.addOperand(MCOperand::createImm(LImm));
242
Inst.addOperand(MCOperand::createImm(0));
243
return MCDisassembler::Success;
244
}
245
246
static DecodeStatus DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn,
247
uint64_t Address,
248
const MCDisassembler *Decoder) {
249
unsigned DstA, SrcB, LImm;
250
LLVM_DEBUG(dbgs() << "Decoding LdLImm:\n");
251
SrcB = decodeBField(Insn);
252
if (SrcB != 62) {
253
LLVM_DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");
254
return MCDisassembler::Fail;
255
}
256
DstA = decodeAField(Insn);
257
DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
258
LImm = (Insn >> 32);
259
Inst.addOperand(MCOperand::createImm(LImm));
260
Inst.addOperand(MCOperand::createImm(0));
261
return MCDisassembler::Success;
262
}
263
264
static DecodeStatus DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn,
265
uint64_t Address,
266
const MCDisassembler *Decoder) {
267
unsigned DstA, SrcB;
268
LLVM_DEBUG(dbgs() << "Decoding LdRLimm\n");
269
DstA = decodeAField(Insn);
270
DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
271
SrcB = decodeBField(Insn);
272
DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);
273
if (decodeCField(Insn) != 62) {
274
LLVM_DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");
275
return MCDisassembler::Fail;
276
}
277
Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32)));
278
return MCDisassembler::Success;
279
}
280
281
static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,
282
uint64_t Address,
283
const MCDisassembler *Decoder) {
284
LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");
285
using Field = decltype(Insn);
286
Field H = fieldFromInstruction(Insn, 5, 3) |
287
(fieldFromInstruction(Insn, 0, 2) << 3);
288
Field G = fieldFromInstruction(Insn, 8, 3) |
289
(fieldFromInstruction(Insn, 3, 2) << 3);
290
291
auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,
292
Field Value) {
293
if (30 == RegNum) {
294
Inst.addOperand(MCOperand::createImm(Value));
295
return MCDisassembler::Success;
296
}
297
298
return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);
299
};
300
301
if (MCDisassembler::Success != DecodeRegisterOrImm(G, 0))
302
return MCDisassembler::Fail;
303
304
return DecodeRegisterOrImm(H, Insn >> 16u);
305
}
306
307
static DecodeStatus DecodeCCRU6Instruction(MCInst &Inst, uint64_t Insn,
308
uint64_t Address,
309
const MCDisassembler *Decoder) {
310
unsigned DstB;
311
LLVM_DEBUG(dbgs() << "Decoding CCRU6 instruction:\n");
312
DstB = decodeBField(Insn);
313
DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
314
using Field = decltype(Insn);
315
Field U6Field = fieldFromInstruction(Insn, 6, 6);
316
Inst.addOperand(MCOperand::createImm(U6Field));
317
Field CCField = fieldFromInstruction(Insn, 0, 4);
318
Inst.addOperand(MCOperand::createImm(CCField));
319
return MCDisassembler::Success;
320
}
321
322
static DecodeStatus DecodeSOPwithRU6(MCInst &Inst, uint64_t Insn,
323
uint64_t Address,
324
const MCDisassembler *Decoder) {
325
unsigned DstB = decodeBField(Insn);
326
DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
327
using Field = decltype(Insn);
328
Field U6 = fieldFromInstruction(Insn, 6, 6);
329
Inst.addOperand(MCOperand::createImm(U6));
330
return MCDisassembler::Success;
331
}
332
333
static DecodeStatus DecodeSOPwithRS12(MCInst &Inst, uint64_t Insn,
334
uint64_t Address,
335
const MCDisassembler *Decoder) {
336
unsigned DstB = decodeBField(Insn);
337
DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
338
using Field = decltype(Insn);
339
Field Lower = fieldFromInstruction(Insn, 6, 6);
340
Field Upper = fieldFromInstruction(Insn, 0, 5);
341
Field Sign = fieldFromInstruction(Insn, 5, 1) ? -1 : 1;
342
Field Result = Sign * ((Upper << 6) + Lower);
343
Inst.addOperand(MCOperand::createImm(Result));
344
return MCDisassembler::Success;
345
}
346
347
DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
348
ArrayRef<uint8_t> Bytes,
349
uint64_t Address,
350
raw_ostream &cStream) const {
351
MCDisassembler::DecodeStatus Result;
352
if (Bytes.size() < 2) {
353
Size = 0;
354
return Fail;
355
}
356
uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;
357
// 0x00 -> 0x07 are 32-bit instructions.
358
// 0x08 -> 0x1F are 16-bit instructions.
359
if (DecodeByte < 0x08) {
360
// 32-bit instruction.
361
if (Bytes.size() < 4) {
362
// Did we decode garbage?
363
Size = 0;
364
return Fail;
365
}
366
if (Bytes.size() >= 8) {
367
// Attempt to decode 64-bit instruction.
368
uint64_t Insn64;
369
if (!readInstruction64(Bytes, Address, Size, Insn64))
370
return Fail;
371
Result =
372
decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
373
if (Success == Result) {
374
LLVM_DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
375
return Result;
376
}
377
LLVM_DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
378
}
379
uint32_t Insn32;
380
if (!readInstruction32(Bytes, Address, Size, Insn32)) {
381
return Fail;
382
}
383
// Calling the auto-generated decoder function.
384
return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
385
} else {
386
if (Bytes.size() >= 6) {
387
// Attempt to treat as instr. with limm data.
388
uint64_t Insn48;
389
if (!readInstruction48(Bytes, Address, Size, Insn48))
390
return Fail;
391
Result =
392
decodeInstruction(DecoderTable48, Instr, Insn48, Address, this, STI);
393
if (Success == Result) {
394
LLVM_DEBUG(
395
dbgs() << "Successfully decoded 16-bit instruction with limm.");
396
return Result;
397
}
398
LLVM_DEBUG(
399
dbgs() << "Not a 16-bit instruction with limm, try without it.");
400
}
401
402
uint32_t Insn16;
403
if (!readInstruction16(Bytes, Address, Size, Insn16))
404
return Fail;
405
406
// Calling the auto-generated decoder function.
407
return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
408
}
409
}
410
411
static MCDisassembler *createARCDisassembler(const Target &T,
412
const MCSubtargetInfo &STI,
413
MCContext &Ctx) {
414
return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());
415
}
416
417
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARCDisassembler() {
418
// Register the disassembler.
419
TargetRegistry::RegisterMCDisassembler(getTheARCTarget(),
420
createARCDisassembler);
421
}
422
423