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/MCFixedLenDisassembler.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/MC/MCSubtargetInfo.h"
22 #include "llvm/Support/MathExtras.h"
23 #include "llvm/Support/TargetRegistry.h"
27 typedef MCDisassembler::DecodeStatus DecodeStatus
;
30 Target
&getTheLanaiTarget();
33 static MCDisassembler
*createLanaiDisassembler(const Target
& /*T*/,
34 const MCSubtargetInfo
&STI
,
36 return new LanaiDisassembler(STI
, Ctx
);
39 extern "C" void LLVMInitializeLanaiDisassembler() {
40 // Register the disassembler
41 TargetRegistry::RegisterMCDisassembler(getTheLanaiTarget(),
42 createLanaiDisassembler
);
45 LanaiDisassembler::LanaiDisassembler(const MCSubtargetInfo
&STI
, MCContext
&Ctx
)
46 : MCDisassembler(STI
, Ctx
) {}
48 // Forward declare because the autogenerated code will reference this.
49 // Definition is further down.
50 static DecodeStatus
DecodeGPRRegisterClass(MCInst
&Inst
, unsigned RegNo
,
54 static DecodeStatus
decodeRiMemoryValue(MCInst
&Inst
, unsigned Insn
,
55 uint64_t Address
, const void *Decoder
);
57 static DecodeStatus
decodeRrMemoryValue(MCInst
&Inst
, unsigned Insn
,
58 uint64_t Address
, const void *Decoder
);
60 static DecodeStatus
decodeSplsValue(MCInst
&Inst
, unsigned Insn
,
61 uint64_t Address
, const void *Decoder
);
63 static DecodeStatus
decodeBranch(MCInst
&Inst
, unsigned Insn
, uint64_t Address
,
66 static DecodeStatus
decodePredicateOperand(MCInst
&Inst
, unsigned Val
,
70 static DecodeStatus
decodeShiftImm(MCInst
&Inst
, unsigned Insn
,
71 uint64_t Address
, const void *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
));
131 DecodeStatus
LanaiDisassembler::getInstruction(
132 MCInst
&Instr
, uint64_t &Size
, ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
133 raw_ostream
& /*VStream*/, raw_ostream
& /*CStream*/) const {
136 DecodeStatus Result
= readInstruction32(Bytes
, Size
, Insn
);
138 if (Result
== MCDisassembler::Fail
)
139 return MCDisassembler::Fail
;
141 // Call auto-generated decoder function
143 decodeInstruction(DecoderTableLanai32
, Instr
, Insn
, Address
, this, STI
);
145 if (Result
!= MCDisassembler::Fail
) {
146 PostOperandDecodeAdjust(Instr
, Insn
);
151 return MCDisassembler::Fail
;
154 static const unsigned GPRDecoderTable
[] = {
155 Lanai::R0
, Lanai::R1
, Lanai::PC
, Lanai::R3
, Lanai::SP
, Lanai::FP
,
156 Lanai::R6
, Lanai::R7
, Lanai::RV
, Lanai::R9
, Lanai::RR1
, Lanai::RR2
,
157 Lanai::R12
, Lanai::R13
, Lanai::R14
, Lanai::RCA
, Lanai::R16
, Lanai::R17
,
158 Lanai::R18
, Lanai::R19
, Lanai::R20
, Lanai::R21
, Lanai::R22
, Lanai::R23
,
159 Lanai::R24
, Lanai::R25
, Lanai::R26
, Lanai::R27
, Lanai::R28
, Lanai::R29
,
160 Lanai::R30
, Lanai::R31
};
162 DecodeStatus
DecodeGPRRegisterClass(MCInst
&Inst
, unsigned RegNo
,
163 uint64_t /*Address*/,
164 const void * /*Decoder*/) {
166 return MCDisassembler::Fail
;
168 unsigned Reg
= GPRDecoderTable
[RegNo
];
169 Inst
.addOperand(MCOperand::createReg(Reg
));
170 return MCDisassembler::Success
;
173 static DecodeStatus
decodeRiMemoryValue(MCInst
&Inst
, unsigned Insn
,
174 uint64_t Address
, const void *Decoder
) {
175 // RI memory values encoded using 23 bits:
176 // 5 bit register, 16 bit constant
177 unsigned Register
= (Insn
>> 18) & 0x1f;
178 Inst
.addOperand(MCOperand::createReg(GPRDecoderTable
[Register
]));
179 unsigned Offset
= (Insn
& 0xffff);
180 Inst
.addOperand(MCOperand::createImm(SignExtend32
<16>(Offset
)));
182 return MCDisassembler::Success
;
185 static DecodeStatus
decodeRrMemoryValue(MCInst
&Inst
, unsigned Insn
,
186 uint64_t Address
, const void *Decoder
) {
187 // RR memory values encoded using 20 bits:
188 // 5 bit register, 5 bit register, 2 bit PQ, 3 bit ALU operator, 5 bit JJJJJ
189 unsigned Register
= (Insn
>> 15) & 0x1f;
190 Inst
.addOperand(MCOperand::createReg(GPRDecoderTable
[Register
]));
191 Register
= (Insn
>> 10) & 0x1f;
192 Inst
.addOperand(MCOperand::createReg(GPRDecoderTable
[Register
]));
194 return MCDisassembler::Success
;
197 static DecodeStatus
decodeSplsValue(MCInst
&Inst
, unsigned Insn
,
198 uint64_t Address
, const void *Decoder
) {
199 // RI memory values encoded using 17 bits:
200 // 5 bit register, 10 bit constant
201 unsigned Register
= (Insn
>> 12) & 0x1f;
202 Inst
.addOperand(MCOperand::createReg(GPRDecoderTable
[Register
]));
203 unsigned Offset
= (Insn
& 0x3ff);
204 Inst
.addOperand(MCOperand::createImm(SignExtend32
<10>(Offset
)));
206 return MCDisassembler::Success
;
209 static bool tryAddingSymbolicOperand(int64_t Value
, bool IsBranch
,
210 uint64_t Address
, uint64_t Offset
,
211 uint64_t Width
, MCInst
&MI
,
212 const void *Decoder
) {
213 const MCDisassembler
*Dis
= static_cast<const MCDisassembler
*>(Decoder
);
214 return Dis
->tryAddingSymbolicOperand(MI
, Value
, Address
, IsBranch
, Offset
,
218 static DecodeStatus
decodeBranch(MCInst
&MI
, unsigned Insn
, uint64_t Address
,
219 const void *Decoder
) {
220 if (!tryAddingSymbolicOperand(Insn
+ Address
, false, Address
, 2, 23, MI
,
222 MI
.addOperand(MCOperand::createImm(Insn
));
223 return MCDisassembler::Success
;
226 static DecodeStatus
decodeShiftImm(MCInst
&Inst
, unsigned Insn
,
227 uint64_t Address
, const void *Decoder
) {
228 unsigned Offset
= (Insn
& 0xffff);
229 Inst
.addOperand(MCOperand::createImm(SignExtend32
<16>(Offset
)));
231 return MCDisassembler::Success
;
234 static DecodeStatus
decodePredicateOperand(MCInst
&Inst
, unsigned Val
,
236 const void *Decoder
) {
237 if (Val
>= LPCC::UNKNOWN
)
238 return MCDisassembler::Fail
;
239 Inst
.addOperand(MCOperand::createImm(Val
));
240 return MCDisassembler::Success
;