1 //===- LanaiDisassembler.cpp - Disassembler for Lanai -----------*- 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 //===----------------------------------------------------------------------===//
9 // This file is part of the Lanai Disassembler.
11 //===----------------------------------------------------------------------===//
13 #include "LanaiDisassembler.h"
15 #include "LanaiAluCode.h"
16 #include "LanaiCondCode.h"
17 #include "LanaiInstrInfo.h"
18 #include "TargetInfo/LanaiTargetInfo.h"
19 #include "llvm/MC/MCDecoderOps.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/MC/MCSubtargetInfo.h"
22 #include "llvm/MC/TargetRegistry.h"
23 #include "llvm/Support/MathExtras.h"
27 typedef MCDisassembler::DecodeStatus DecodeStatus
;
29 static MCDisassembler
*createLanaiDisassembler(const Target
& /*T*/,
30 const MCSubtargetInfo
&STI
,
32 return new LanaiDisassembler(STI
, Ctx
);
35 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeLanaiDisassembler() {
36 // Register the disassembler
37 TargetRegistry::RegisterMCDisassembler(getTheLanaiTarget(),
38 createLanaiDisassembler
);
41 LanaiDisassembler::LanaiDisassembler(const MCSubtargetInfo
&STI
, MCContext
&Ctx
)
42 : MCDisassembler(STI
, Ctx
) {}
44 // Forward declare because the autogenerated code will reference this.
45 // Definition is further down.
46 static DecodeStatus
DecodeGPRRegisterClass(MCInst
&Inst
, unsigned RegNo
,
48 const MCDisassembler
*Decoder
);
50 static DecodeStatus
decodeRiMemoryValue(MCInst
&Inst
, unsigned Insn
,
52 const MCDisassembler
*Decoder
);
54 static DecodeStatus
decodeRrMemoryValue(MCInst
&Inst
, unsigned Insn
,
56 const MCDisassembler
*Decoder
);
58 static DecodeStatus
decodeSplsValue(MCInst
&Inst
, unsigned Insn
,
60 const MCDisassembler
*Decoder
);
62 static DecodeStatus
decodeBranch(MCInst
&Inst
, unsigned Insn
, uint64_t Address
,
63 const MCDisassembler
*Decoder
);
65 static DecodeStatus
decodePredicateOperand(MCInst
&Inst
, unsigned Val
,
67 const MCDisassembler
*Decoder
);
69 static DecodeStatus
decodeShiftImm(MCInst
&Inst
, unsigned Insn
,
71 const MCDisassembler
*Decoder
);
73 #include "LanaiGenDisassemblerTables.inc"
75 static DecodeStatus
readInstruction32(ArrayRef
<uint8_t> Bytes
, uint64_t &Size
,
77 // We want to read exactly 4 bytes of data.
78 if (Bytes
.size() < 4) {
80 return MCDisassembler::Fail
;
83 // Encoded as big-endian 32-bit word in the stream.
85 (Bytes
[0] << 24) | (Bytes
[1] << 16) | (Bytes
[2] << 8) | (Bytes
[3] << 0);
87 return MCDisassembler::Success
;
90 static void PostOperandDecodeAdjust(MCInst
&Instr
, uint32_t Insn
) {
91 unsigned AluOp
= LPAC::ADD
;
92 // Fix up for pre and post operations.
94 if (isRMOpcode(Instr
.getOpcode()))
96 else if (isSPLSOpcode(Instr
.getOpcode()))
98 else if (isRRMOpcode(Instr
.getOpcode())) {
100 // Determine RRM ALU op.
101 AluOp
= (Insn
>> 8) & 0x7;
104 // 0b10000 or 0b11000
105 AluOp
|= 0x20 | (((Insn
>> 3) & 0xf) << 1);
109 unsigned PQ
= (Insn
>> PqShift
) & 0x3;
112 if (Instr
.getOperand(2).isReg()) {
113 Instr
.getOperand(2).setReg(Lanai::R0
);
115 if (Instr
.getOperand(2).isImm())
116 Instr
.getOperand(2).setImm(0);
119 AluOp
= LPAC::makePostOp(AluOp
);
124 AluOp
= LPAC::makePreOp(AluOp
);
127 Instr
.addOperand(MCOperand::createImm(AluOp
));
132 LanaiDisassembler::getInstruction(MCInst
&Instr
, uint64_t &Size
,
133 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
134 raw_ostream
& /*CStream*/) const {
137 DecodeStatus Result
= readInstruction32(Bytes
, Size
, Insn
);
139 if (Result
== MCDisassembler::Fail
)
140 return MCDisassembler::Fail
;
142 // Call auto-generated decoder function
144 decodeInstruction(DecoderTableLanai32
, Instr
, Insn
, Address
, this, STI
);
146 if (Result
!= MCDisassembler::Fail
) {
147 PostOperandDecodeAdjust(Instr
, Insn
);
152 return MCDisassembler::Fail
;
155 static const unsigned GPRDecoderTable
[] = {
156 Lanai::R0
, Lanai::R1
, Lanai::PC
, Lanai::R3
, Lanai::SP
, Lanai::FP
,
157 Lanai::R6
, Lanai::R7
, Lanai::RV
, Lanai::R9
, Lanai::RR1
, Lanai::RR2
,
158 Lanai::R12
, Lanai::R13
, Lanai::R14
, Lanai::RCA
, Lanai::R16
, Lanai::R17
,
159 Lanai::R18
, Lanai::R19
, Lanai::R20
, Lanai::R21
, Lanai::R22
, Lanai::R23
,
160 Lanai::R24
, Lanai::R25
, Lanai::R26
, Lanai::R27
, Lanai::R28
, Lanai::R29
,
161 Lanai::R30
, Lanai::R31
};
163 DecodeStatus
DecodeGPRRegisterClass(MCInst
&Inst
, unsigned RegNo
,
164 uint64_t /*Address*/,
165 const MCDisassembler
* /*Decoder*/) {
167 return MCDisassembler::Fail
;
169 unsigned Reg
= GPRDecoderTable
[RegNo
];
170 Inst
.addOperand(MCOperand::createReg(Reg
));
171 return MCDisassembler::Success
;
174 static DecodeStatus
decodeRiMemoryValue(MCInst
&Inst
, unsigned Insn
,
176 const MCDisassembler
*Decoder
) {
177 // RI memory values encoded using 23 bits:
178 // 5 bit register, 16 bit constant
179 unsigned Register
= (Insn
>> 18) & 0x1f;
180 Inst
.addOperand(MCOperand::createReg(GPRDecoderTable
[Register
]));
181 unsigned Offset
= (Insn
& 0xffff);
182 Inst
.addOperand(MCOperand::createImm(SignExtend32
<16>(Offset
)));
184 return MCDisassembler::Success
;
187 static DecodeStatus
decodeRrMemoryValue(MCInst
&Inst
, unsigned Insn
,
189 const MCDisassembler
*Decoder
) {
190 // RR memory values encoded using 20 bits:
191 // 5 bit register, 5 bit register, 2 bit PQ, 3 bit ALU operator, 5 bit JJJJJ
192 unsigned Register
= (Insn
>> 15) & 0x1f;
193 Inst
.addOperand(MCOperand::createReg(GPRDecoderTable
[Register
]));
194 Register
= (Insn
>> 10) & 0x1f;
195 Inst
.addOperand(MCOperand::createReg(GPRDecoderTable
[Register
]));
197 return MCDisassembler::Success
;
200 static DecodeStatus
decodeSplsValue(MCInst
&Inst
, unsigned Insn
,
202 const MCDisassembler
*Decoder
) {
203 // RI memory values encoded using 17 bits:
204 // 5 bit register, 10 bit constant
205 unsigned Register
= (Insn
>> 12) & 0x1f;
206 Inst
.addOperand(MCOperand::createReg(GPRDecoderTable
[Register
]));
207 unsigned Offset
= (Insn
& 0x3ff);
208 Inst
.addOperand(MCOperand::createImm(SignExtend32
<10>(Offset
)));
210 return MCDisassembler::Success
;
213 static bool tryAddingSymbolicOperand(int64_t Value
, bool IsBranch
,
214 uint64_t Address
, uint64_t Offset
,
215 uint64_t Width
, MCInst
&MI
,
216 const MCDisassembler
*Decoder
) {
217 return Decoder
->tryAddingSymbolicOperand(MI
, Value
, Address
, IsBranch
, Offset
,
218 Width
, /*InstSize=*/0);
221 static DecodeStatus
decodeBranch(MCInst
&MI
, unsigned Insn
, uint64_t Address
,
222 const MCDisassembler
*Decoder
) {
223 if (!tryAddingSymbolicOperand(Insn
+ Address
, false, Address
, 2, 23, MI
,
225 MI
.addOperand(MCOperand::createImm(Insn
));
226 return MCDisassembler::Success
;
229 static DecodeStatus
decodeShiftImm(MCInst
&Inst
, unsigned Insn
,
231 const MCDisassembler
*Decoder
) {
232 unsigned Offset
= (Insn
& 0xffff);
233 Inst
.addOperand(MCOperand::createImm(SignExtend32
<16>(Offset
)));
235 return MCDisassembler::Success
;
238 static DecodeStatus
decodePredicateOperand(MCInst
&Inst
, unsigned Val
,
240 const MCDisassembler
*Decoder
) {
241 if (Val
>= LPCC::UNKNOWN
)
242 return MCDisassembler::Fail
;
243 Inst
.addOperand(MCOperand::createImm(Val
));
244 return MCDisassembler::Success
;