LLVM 22.0.0git
CSKYDisassembler.cpp
Go to the documentation of this file.
1//===-- CSKYDisassembler.cpp - Disassembler for CSKY ----------------------===//
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 CSKYDisassembler class.
10//
11//===----------------------------------------------------------------------===//
12
16#include "llvm/ADT/DenseMap.h"
17#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCDecoder.h"
21#include "llvm/MC/MCInst.h"
22#include "llvm/MC/MCInstrInfo.h"
26#include "llvm/Support/Endian.h"
27
28using namespace llvm;
29
30#define DEBUG_TYPE "csky-disassembler"
31
33
34namespace {
35class CSKYDisassembler : public MCDisassembler {
36 std::unique_ptr<MCInstrInfo const> const MCII;
37 mutable StringRef symbolName;
38
39 DecodeStatus handleCROperand(MCInst &Instr) const;
40
41public:
42 CSKYDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
43 MCInstrInfo const *MCII);
44
47 raw_ostream &CStream) const override;
48};
49} // end anonymous namespace
50
51CSKYDisassembler::CSKYDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
52 MCInstrInfo const *MCII)
53 : MCDisassembler(STI, Ctx), MCII(MCII) {}
54
56 const MCSubtargetInfo &STI,
57 MCContext &Ctx) {
58 return new CSKYDisassembler(STI, Ctx, T.createMCInstrInfo());
59}
60
64}
65
66static const uint16_t GPRDecoderTable[] = {
67 CSKY::R0, CSKY::R1, CSKY::R2, CSKY::R3, CSKY::R4, CSKY::R5, CSKY::R6,
68 CSKY::R7, CSKY::R8, CSKY::R9, CSKY::R10, CSKY::R11, CSKY::R12, CSKY::R13,
69 CSKY::R14, CSKY::R15, CSKY::R16, CSKY::R17, CSKY::R18, CSKY::R19, CSKY::R20,
70 CSKY::R21, CSKY::R22, CSKY::R23, CSKY::R24, CSKY::R25, CSKY::R26, CSKY::R27,
71 CSKY::R28, CSKY::R29, CSKY::R30, CSKY::R31};
72
73static const uint16_t GPRPairDecoderTable[] = {
74 CSKY::R0_R1, CSKY::R1_R2, CSKY::R2_R3, CSKY::R3_R4, CSKY::R4_R5,
75 CSKY::R5_R6, CSKY::R6_R7, CSKY::R7_R8, CSKY::R8_R9, CSKY::R9_R10,
76 CSKY::R10_R11, CSKY::R11_R12, CSKY::R12_R13, CSKY::R13_R14, CSKY::R14_R15,
77 CSKY::R15_R16, CSKY::R16_R17, CSKY::R17_R18, CSKY::R18_R19, CSKY::R19_R20,
78 CSKY::R20_R21, CSKY::R21_R22, CSKY::R22_R23, CSKY::R23_R24, CSKY::R24_R25,
79 CSKY::R25_R26, CSKY::R26_R27, CSKY::R27_R28, CSKY::R28_R29, CSKY::R29_R30,
80 CSKY::R30_R31, CSKY::R31_R32};
81
82static const uint16_t FPR32DecoderTable[] = {
83 CSKY::F0_32, CSKY::F1_32, CSKY::F2_32, CSKY::F3_32, CSKY::F4_32,
84 CSKY::F5_32, CSKY::F6_32, CSKY::F7_32, CSKY::F8_32, CSKY::F9_32,
85 CSKY::F10_32, CSKY::F11_32, CSKY::F12_32, CSKY::F13_32, CSKY::F14_32,
86 CSKY::F15_32, CSKY::F16_32, CSKY::F17_32, CSKY::F18_32, CSKY::F19_32,
87 CSKY::F20_32, CSKY::F21_32, CSKY::F22_32, CSKY::F23_32, CSKY::F24_32,
88 CSKY::F25_32, CSKY::F26_32, CSKY::F27_32, CSKY::F28_32, CSKY::F29_32,
89 CSKY::F30_32, CSKY::F31_32};
90
91static const uint16_t FPR64DecoderTable[] = {
92 CSKY::F0_64, CSKY::F1_64, CSKY::F2_64, CSKY::F3_64, CSKY::F4_64,
93 CSKY::F5_64, CSKY::F6_64, CSKY::F7_64, CSKY::F8_64, CSKY::F9_64,
94 CSKY::F10_64, CSKY::F11_64, CSKY::F12_64, CSKY::F13_64, CSKY::F14_64,
95 CSKY::F15_64, CSKY::F16_64, CSKY::F17_64, CSKY::F18_64, CSKY::F19_64,
96 CSKY::F20_64, CSKY::F21_64, CSKY::F22_64, CSKY::F23_64, CSKY::F24_64,
97 CSKY::F25_64, CSKY::F26_64, CSKY::F27_64, CSKY::F28_64, CSKY::F29_64,
98 CSKY::F30_64, CSKY::F31_64};
99
100static const uint16_t FPR128DecoderTable[] = {
101 CSKY::F0_128, CSKY::F1_128, CSKY::F2_128, CSKY::F3_128, CSKY::F4_128,
102 CSKY::F5_128, CSKY::F6_128, CSKY::F7_128, CSKY::F8_128, CSKY::F9_128,
103 CSKY::F10_128, CSKY::F11_128, CSKY::F12_128, CSKY::F13_128, CSKY::F14_128,
104 CSKY::F15_128, CSKY::F16_128, CSKY::F17_128, CSKY::F18_128, CSKY::F19_128,
105 CSKY::F20_128, CSKY::F21_128, CSKY::F22_128, CSKY::F23_128, CSKY::F24_128,
106 CSKY::F25_128, CSKY::F26_128, CSKY::F27_128, CSKY::F28_128, CSKY::F29_128,
107 CSKY::F30_128, CSKY::F31_128};
108
110 uint64_t Address,
111 const MCDisassembler *Decoder) {
112 if (RegNo >= 32)
114
117}
118
120 uint64_t Address,
121 const MCDisassembler *Decoder) {
122 if (RegNo >= 32)
124
127}
128
130 uint64_t Address,
131 const MCDisassembler *Decoder) {
132 if (RegNo >= 16)
134
137}
138
140 uint64_t Address,
141 const MCDisassembler *Decoder) {
142 if (RegNo >= 16)
144
147}
148
150 uint64_t Address,
151 const MCDisassembler *Decoder) {
152 if (RegNo >= 16)
154
157}
158
160 uint64_t Address,
161 const MCDisassembler *Decoder) {
162 if (RegNo >= 32)
164
167}
168
169// TODO
172 uint64_t Address,
173 const MCDisassembler *Decoder) {
174 if (RegNo >= 16)
176
179}
180
182 uint64_t Address,
183 const MCDisassembler *Decoder) {
184 if (RegNo >= 16)
186
189}
190
192 uint64_t Address,
193 const MCDisassembler *Decoder) {
194 if (RegNo >= 8)
196
199}
200
201// TODO
204 uint64_t Address,
205 const MCDisassembler *Decoder) {
206 if (RegNo != 14)
208
211}
212
214 uint64_t Address,
215 const MCDisassembler *Decoder) {
216 const FeatureBitset &FeatureBits =
217 Decoder->getSubtargetInfo().getFeatureBits();
218 bool hasHighReg = FeatureBits[CSKY::FeatureHighreg];
219
220 if (RegNo >= 32 || (!hasHighReg && RegNo >= 16))
222
225}
226
227template <unsigned N, unsigned S>
229 int64_t Address,
230 const MCDisassembler *Decoder) {
231 assert(isUInt<N>(Imm) && "Invalid immediate");
232 Inst.addOperand(MCOperand::createImm(Imm << S));
234}
235
236template <unsigned N>
238 int64_t Address,
239 const MCDisassembler *Decoder) {
240 assert(isUInt<N>(Imm) && "Invalid immediate");
241 Inst.addOperand(MCOperand::createImm(Imm + 1));
243}
244
245static DecodeStatus decodeLRW16Imm8(MCInst &Inst, uint64_t Imm, int64_t Address,
246 const MCDisassembler *Decoder) {
247 assert(isUInt<8>(Imm) && "Invalid immediate");
248 if ((Imm >> 7) & 0x1) {
249 Inst.addOperand(MCOperand::createImm((Imm & 0x7F) << 2));
250 } else {
251 uint64_t V = ((Imm ^ 0xFFFFFFFF) & 0xFF);
252 Inst.addOperand(MCOperand::createImm(V << 2));
253 }
254
256}
257
259 int64_t Address,
260 const MCDisassembler *Decoder) {
261 assert(isUInt<2>(Imm) && "Invalid immediate");
262
263 if (Imm == 0)
265 else if (Imm == 1)
267 else if (Imm == 2)
269 else if (Imm == 3)
271 else
273
275}
276
278 int64_t Address,
279 const MCDisassembler *Decoder) {
280 assert(isUInt<10>(Imm) && "Invalid immediate");
281
282 auto Imm5 = Imm & 0x1f;
283 auto Ry = (Imm >> 5) & 0x1f;
284
285 if (DecodeGPRRegisterClass(Inst, Ry, Address, Decoder) ==
288
290
292}
293
295 int64_t Address,
296 const MCDisassembler *Decoder) {
297 assert(isUInt<10>(Imm) && "Invalid immediate");
298
299 auto Imm5 = Imm & 0x1f;
300 auto Ry = (Imm >> 5) & 0x1f;
301
302 if (DecodesFPR32RegisterClass(Inst, Ry, Address, Decoder) ==
305
307
309}
310
312 int64_t Address,
313 const MCDisassembler *Decoder) {
314 assert(isUInt<10>(Imm) && "Invalid immediate");
315
316 auto Imm5 = Imm & 0x1f;
317 auto Ry = (Imm >> 5) & 0x1f;
318
319 if (DecodesFPR64RegisterClass(Inst, Ry, Address, Decoder) ==
322
324
326}
327
329 int64_t Address,
330 const MCDisassembler *Decoder) {
331 assert(isUInt<10>(Imm) && "Invalid immediate");
332
333 auto Imm5 = Imm & 0x1f;
334 auto Ry = (Imm >> 5) & 0x1f;
335
336 if (DecodeFPR32RegisterClass(Inst, Ry, Address, Decoder) ==
339
341
343}
344
346 int64_t Address,
347 const MCDisassembler *Decoder) {
348 assert(isUInt<10>(Imm) && "Invalid immediate");
349
350 auto Imm5 = Imm & 0x1f;
351 auto Ry = (Imm >> 5) & 0x1f;
352
353 if (DecodeFPR64RegisterClass(Inst, Ry, Address, Decoder) ==
356
358
360}
361
363 int64_t Address,
364 const MCDisassembler *Decoder) {
367}
368
369template <unsigned N, unsigned S>
371 int64_t Address,
372 const MCDisassembler *Decoder) {
373 assert(isUInt<N>(Imm) && "Invalid immediate");
374 // Sign-extend the number in the bottom N bits of Imm
375 Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm) << S));
377}
378
379#include "CSKYGenDisassemblerTables.inc"
380
381DecodeStatus CSKYDisassembler::handleCROperand(MCInst &MI) const {
382
383 // FIXME: To query instruction info from td file or a table inc file
384 switch (MI.getOpcode()) {
385 default:
387 case CSKY::LD16WSP:
388 case CSKY::ST16WSP:
389 case CSKY::ADDI16ZSP:
390 MI.insert(std::next(MI.begin()), MCOperand::createReg(CSKY::R14));
392 case CSKY::ADDI16SPSP:
393 case CSKY::SUBI16SPSP:
394 MI.insert(MI.begin(), MCOperand::createReg(CSKY::R14));
395 MI.insert(MI.begin(), MCOperand::createReg(CSKY::R14));
397 case CSKY::FCMPHS_S:
398 case CSKY::FCMPHS_D:
399 case CSKY::FCMPLT_S:
400 case CSKY::FCMPLT_D:
401 case CSKY::FCMPNE_S:
402 case CSKY::FCMPNE_D:
403 case CSKY::FCMPUO_S:
404 case CSKY::FCMPUO_D:
405 case CSKY::FCMPZHS_S:
406 case CSKY::FCMPZHS_D:
407 case CSKY::FCMPZLS_S:
408 case CSKY::FCMPZLS_D:
409 case CSKY::FCMPZNE_S:
410 case CSKY::FCMPZNE_D:
411 case CSKY::FCMPZUO_S:
412 case CSKY::FCMPZUO_D:
413 case CSKY::f2FCMPHS_S:
414 case CSKY::f2FCMPHS_D:
415 case CSKY::f2FCMPLT_S:
416 case CSKY::f2FCMPLT_D:
417 case CSKY::f2FCMPNE_S:
418 case CSKY::f2FCMPNE_D:
419 case CSKY::f2FCMPUO_S:
420 case CSKY::f2FCMPUO_D:
421 case CSKY::f2FCMPHSZ_S:
422 case CSKY::f2FCMPHSZ_D:
423 case CSKY::f2FCMPHZ_S:
424 case CSKY::f2FCMPHZ_D:
425 case CSKY::f2FCMPLSZ_S:
426 case CSKY::f2FCMPLSZ_D:
427 case CSKY::f2FCMPLTZ_S:
428 case CSKY::f2FCMPLTZ_D:
429 case CSKY::f2FCMPNEZ_S:
430 case CSKY::f2FCMPNEZ_D:
431 case CSKY::f2FCMPUOZ_S:
432 case CSKY::f2FCMPUOZ_D:
433
434 case CSKY::BT32:
435 case CSKY::BF32:
436 case CSKY::BT16:
437 case CSKY::BF16:
438 case CSKY::CMPNEI32:
439 case CSKY::CMPNEI16:
440 case CSKY::CMPNE32:
441 case CSKY::CMPNE16:
442 case CSKY::CMPHSI32:
443 case CSKY::CMPHSI16:
444 case CSKY::CMPHS32:
445 case CSKY::CMPHS16:
446 case CSKY::CMPLTI32:
447 case CSKY::CMPLTI16:
448 case CSKY::CMPLT32:
449 case CSKY::CMPLT16:
450 case CSKY::BTSTI32:
451 case CSKY::BTSTI16:
452 case CSKY::TSTNBZ32:
453 case CSKY::TSTNBZ16:
454 case CSKY::TST32:
455 case CSKY::TST16:
456 MI.insert(MI.begin(), MCOperand::createReg(CSKY::C));
458 case CSKY::LSLC32:
459 case CSKY::LSRC32:
460 case CSKY::ASRC32:
461 MI.insert(std::next(MI.begin()), MCOperand::createReg(CSKY::C));
463 case CSKY::MOVF32:
464 case CSKY::MOVT32:
465 case CSKY::MVC32:
466 case CSKY::MVCV32:
467 case CSKY::MVCV16:
468 case CSKY::INCT32:
469 case CSKY::INCF32:
470 case CSKY::DECT32:
471 case CSKY::DECF32:
472 case CSKY::DECGT32:
473 case CSKY::DECLT32:
474 case CSKY::DECNE32:
475 case CSKY::CLRF32:
476 case CSKY::CLRT32:
477 case CSKY::f2FSEL_S:
478 case CSKY::f2FSEL_D:
479 MI.insert(std::next(MI.begin()), MCOperand::createReg(CSKY::C));
481 case CSKY::ADDC32:
482 case CSKY::ADDC16:
483 case CSKY::SUBC32:
484 case CSKY::SUBC16:
485 case CSKY::XSR32:
486 MI.insert(std::next(MI.begin()), MCOperand::createReg(CSKY::C));
487 MI.insert(MI.end(), MCOperand::createReg(CSKY::C));
489 case CSKY::INS32:
490 MI.getOperand(3).setImm(MI.getOperand(3).getImm() +
491 MI.getOperand(4).getImm());
493 }
494}
495
497 const MCDisassembler *DisAsm,
498 const MCSubtargetInfo &STI) {
499 LLVM_DEBUG(dbgs() << "Trying CSKY 32-bit fpuv3 table :\n");
500 if (!STI.hasFeature(CSKY::FeatureFPUV3_HF) &&
501 !STI.hasFeature(CSKY::FeatureFPUV3_SF) &&
502 !STI.hasFeature(CSKY::FeatureFPUV3_DF))
503 return false;
504
505 DecodeStatus Result =
506 decodeInstruction(DecoderTableFPUV332, MI, insn, Address, DisAsm, STI);
507
508 if (Result == MCDisassembler::Fail) {
509 MI.clear();
510 return false;
511 }
512
513 return true;
514}
515
516DecodeStatus CSKYDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
517 ArrayRef<uint8_t> Bytes,
518 uint64_t Address,
519 raw_ostream &CS) const {
520
521 uint32_t Insn;
523
524 Insn = support::endian::read16le(Bytes.data());
525
526 if ((Insn >> 14) == 0x3) {
527 if (Bytes.size() < 4) {
528 Size = 0;
530 }
531 Insn = (Insn << 16) | support::endian::read16le(&Bytes[2]);
532
533 if (decodeFPUV3Instruction(MI, Insn, Address, this, STI))
535 else {
536 LLVM_DEBUG(dbgs() << "Trying CSKY 32-bit table :\n");
537 Result = decodeInstruction(DecoderTable32, MI, Insn, Address, this, STI);
538 }
539
540 Size = 4;
541 } else {
542 if (Bytes.size() < 2) {
543 Size = 0;
545 }
546 LLVM_DEBUG(dbgs() << "Trying CSKY 16-bit table :\n");
547 Result = decodeInstruction(DecoderTable16, MI, Insn, Address, this, STI);
548 Size = 2;
549 }
550
551 handleCROperand(MI);
552
553 return Result;
554}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const uint16_t GPRPairDecoderTable[]
static LLVM_ATTRIBUTE_UNUSED DecodeStatus DecodesFPR128RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus DecodeGPRPairRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const MCDisassembler *Decoder)
MCDisassembler::DecodeStatus DecodeStatus
static const uint16_t FPR32DecoderTable[]
static DecodeStatus DecodeRegSeqOperandF2(MCInst &Inst, uint64_t Imm, int64_t Address, const MCDisassembler *Decoder)
static DecodeStatus DecodesFPR32RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const MCDisassembler *Decoder)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYDisassembler()
static DecodeStatus decodeJMPIXImmOperand(MCInst &Inst, uint64_t Imm, int64_t Address, const MCDisassembler *Decoder)
static const uint16_t FPR128DecoderTable[]
static MCDisassembler * createCSKYDisassembler(const Target &T, const MCSubtargetInfo &STI, MCContext &Ctx)
static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus DecodeRegSeqOperand(MCInst &Inst, uint64_t Imm, int64_t Address, const MCDisassembler *Decoder)
static DecodeStatus decodeLRW16Imm8(MCInst &Inst, uint64_t Imm, int64_t Address, const MCDisassembler *Decoder)
static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm, int64_t Address, const MCDisassembler *Decoder)
static DecodeStatus DecodeRegSeqOperandF1(MCInst &Inst, uint64_t Imm, int64_t Address, const MCDisassembler *Decoder)
static DecodeStatus DecodesGPRRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus DecodeRegSeqOperandD2(MCInst &Inst, uint64_t Imm, int64_t Address, const MCDisassembler *Decoder)
static LLVM_ATTRIBUTE_UNUSED DecodeStatus DecodeGPRSPRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus decodeOImmOperand(MCInst &Inst, uint64_t Imm, int64_t Address, const MCDisassembler *Decoder)
static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus decodeImmShiftOpValue(MCInst &Inst, uint64_t Imm, int64_t Address, const MCDisassembler *Decoder)
static DecodeStatus DecodesFPR64_VRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus DecodeRegSeqOperandD1(MCInst &Inst, uint64_t Imm, int64_t Address, const MCDisassembler *Decoder)
static DecodeStatus DecodemGPRRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const MCDisassembler *Decoder)
static const uint16_t GPRDecoderTable[]
static bool decodeFPUV3Instruction(MCInst &MI, uint32_t insn, uint64_t Address, const MCDisassembler *DisAsm, const MCSubtargetInfo &STI)
static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm, int64_t Address, const MCDisassembler *Decoder)
static const uint16_t FPR64DecoderTable[]
static DecodeStatus DecodesFPR64RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const MCDisassembler *Decoder)
#define LLVM_ATTRIBUTE_UNUSED
Definition: Compiler.h:298
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:132
This file defines the DenseMap class.
uint64_t Size
IRTranslator LLVM IR MI
#define LLVM_DEBUG(...)
Definition: Debug.h:119
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
Container class for subtarget features.
Context object for machine code objects.
Definition: MCContext.h:83
Superclass for all disassemblers.
const MCSubtargetInfo & getSubtargetInfo() const
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:188
void addOperand(const MCOperand Op)
Definition: MCInst.h:215
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:27
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.
bool hasFeature(unsigned Feature) const
const FeatureBitset & getFeatureBits() const
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
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
uint16_t read16le(const void *P)
Definition: Endian.h:426
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition: MathExtras.h:342
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:207
Target & getTheCSKYTarget()
static void RegisterMCDisassembler(Target &T, Target::MCDisassemblerCtorTy Fn)
RegisterMCDisassembler - Register a MCDisassembler implementation for the given target.