1 //===-- LoongArchDisassembler.cpp - Disassembler for LoongArch ------------===//
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 //===----------------------------------------------------------------------===//
9 // This file implements the LoongArchDisassembler class.
11 //===----------------------------------------------------------------------===//
13 #include "MCTargetDesc/LoongArchBaseInfo.h"
14 #include "MCTargetDesc/LoongArchMCTargetDesc.h"
15 #include "TargetInfo/LoongArchTargetInfo.h"
16 #include "llvm/MC/MCContext.h"
17 #include "llvm/MC/MCDecoderOps.h"
18 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCInstrInfo.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/MC/MCSubtargetInfo.h"
23 #include "llvm/MC/TargetRegistry.h"
24 #include "llvm/Support/Endian.h"
28 #define DEBUG_TYPE "loongarch-disassembler"
30 typedef MCDisassembler::DecodeStatus DecodeStatus
;
33 class LoongArchDisassembler
: public MCDisassembler
{
35 LoongArchDisassembler(const MCSubtargetInfo
&STI
, MCContext
&Ctx
)
36 : MCDisassembler(STI
, Ctx
) {}
38 DecodeStatus
getInstruction(MCInst
&Instr
, uint64_t &Size
,
39 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
40 raw_ostream
&CStream
) const override
;
44 static MCDisassembler
*createLoongArchDisassembler(const Target
&T
,
45 const MCSubtargetInfo
&STI
,
47 return new LoongArchDisassembler(STI
, Ctx
);
50 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeLoongArchDisassembler() {
51 // Register the disassembler for each target.
52 TargetRegistry::RegisterMCDisassembler(getTheLoongArch32Target(),
53 createLoongArchDisassembler
);
54 TargetRegistry::RegisterMCDisassembler(getTheLoongArch64Target(),
55 createLoongArchDisassembler
);
58 static DecodeStatus
DecodeGPRRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
60 const MCDisassembler
*Decoder
) {
62 return MCDisassembler::Fail
;
63 Inst
.addOperand(MCOperand::createReg(LoongArch::R0
+ RegNo
));
64 return MCDisassembler::Success
;
67 static DecodeStatus
DecodeFPR32RegisterClass(MCInst
&Inst
, uint64_t RegNo
,
69 const MCDisassembler
*Decoder
) {
71 return MCDisassembler::Fail
;
72 Inst
.addOperand(MCOperand::createReg(LoongArch::F0
+ RegNo
));
73 return MCDisassembler::Success
;
76 static DecodeStatus
DecodeFPR64RegisterClass(MCInst
&Inst
, uint64_t RegNo
,
78 const MCDisassembler
*Decoder
) {
80 return MCDisassembler::Fail
;
81 Inst
.addOperand(MCOperand::createReg(LoongArch::F0_64
+ RegNo
));
82 return MCDisassembler::Success
;
85 static DecodeStatus
DecodeCFRRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
87 const MCDisassembler
*Decoder
) {
89 return MCDisassembler::Fail
;
90 Inst
.addOperand(MCOperand::createReg(LoongArch::FCC0
+ RegNo
));
91 return MCDisassembler::Success
;
94 static DecodeStatus
DecodeFCSRRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
96 const MCDisassembler
*Decoder
) {
98 return MCDisassembler::Fail
;
99 Inst
.addOperand(MCOperand::createReg(LoongArch::FCSR0
+ RegNo
));
100 return MCDisassembler::Success
;
103 static DecodeStatus
DecodeLSX128RegisterClass(MCInst
&Inst
, uint64_t RegNo
,
105 const MCDisassembler
*Decoder
) {
107 return MCDisassembler::Fail
;
108 Inst
.addOperand(MCOperand::createReg(LoongArch::VR0
+ RegNo
));
109 return MCDisassembler::Success
;
112 static DecodeStatus
DecodeLASX256RegisterClass(MCInst
&Inst
, uint64_t RegNo
,
114 const MCDisassembler
*Decoder
) {
116 return MCDisassembler::Fail
;
117 Inst
.addOperand(MCOperand::createReg(LoongArch::XR0
+ RegNo
));
118 return MCDisassembler::Success
;
121 static DecodeStatus
DecodeSCRRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
123 const MCDisassembler
*Decoder
) {
125 return MCDisassembler::Fail
;
126 Inst
.addOperand(MCOperand::createReg(LoongArch::SCR0
+ RegNo
));
127 return MCDisassembler::Success
;
130 template <unsigned N
, int P
= 0>
131 static DecodeStatus
decodeUImmOperand(MCInst
&Inst
, uint64_t Imm
,
133 const MCDisassembler
*Decoder
) {
134 assert(isUInt
<N
>(Imm
) && "Invalid immediate");
135 Inst
.addOperand(MCOperand::createImm(Imm
+ P
));
136 return MCDisassembler::Success
;
139 template <unsigned N
, unsigned S
= 0>
140 static DecodeStatus
decodeSImmOperand(MCInst
&Inst
, uint64_t Imm
,
142 const MCDisassembler
*Decoder
) {
143 assert(isUInt
<N
>(Imm
) && "Invalid immediate");
144 // Shift left Imm <S> bits, then sign-extend the number in the bottom <N+S>
146 Inst
.addOperand(MCOperand::createImm(SignExtend64
<N
+ S
>(Imm
<< S
)));
147 return MCDisassembler::Success
;
150 #include "LoongArchGenDisassemblerTables.inc"
152 DecodeStatus
LoongArchDisassembler::getInstruction(MCInst
&MI
, uint64_t &Size
,
153 ArrayRef
<uint8_t> Bytes
,
155 raw_ostream
&CS
) const {
159 // We want to read exactly 4 bytes of data because all LoongArch instructions
160 // are fixed 32 bits.
161 if (Bytes
.size() < 4) {
163 return MCDisassembler::Fail
;
166 Insn
= support::endian::read32le(Bytes
.data());
167 // Calling the auto-generated decoder function.
168 Result
= decodeInstruction(DecoderTable32
, MI
, Insn
, Address
, this, STI
);