1 //===- SparcDisassembler.cpp - Disassembler for Sparc -----------*- 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 Sparc Disassembler.
11 //===----------------------------------------------------------------------===//
13 #include "MCTargetDesc/SparcMCTargetDesc.h"
14 #include "TargetInfo/SparcTargetInfo.h"
15 #include "llvm/MC/MCAsmInfo.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/TargetRegistry.h"
24 #define DEBUG_TYPE "sparc-disassembler"
26 typedef MCDisassembler::DecodeStatus DecodeStatus
;
30 /// A disassembler class for Sparc.
31 class SparcDisassembler
: public MCDisassembler
{
33 SparcDisassembler(const MCSubtargetInfo
&STI
, MCContext
&Ctx
)
34 : MCDisassembler(STI
, Ctx
) {}
35 virtual ~SparcDisassembler() = default;
37 DecodeStatus
getInstruction(MCInst
&Instr
, uint64_t &Size
,
38 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
39 raw_ostream
&CStream
) const override
;
43 static MCDisassembler
*createSparcDisassembler(const Target
&T
,
44 const MCSubtargetInfo
&STI
,
46 return new SparcDisassembler(STI
, Ctx
);
50 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeSparcDisassembler() {
51 // Register the disassembler.
52 TargetRegistry::RegisterMCDisassembler(getTheSparcTarget(),
53 createSparcDisassembler
);
54 TargetRegistry::RegisterMCDisassembler(getTheSparcV9Target(),
55 createSparcDisassembler
);
56 TargetRegistry::RegisterMCDisassembler(getTheSparcelTarget(),
57 createSparcDisassembler
);
60 static const unsigned IntRegDecoderTable
[] = {
61 SP::G0
, SP::G1
, SP::G2
, SP::G3
,
62 SP::G4
, SP::G5
, SP::G6
, SP::G7
,
63 SP::O0
, SP::O1
, SP::O2
, SP::O3
,
64 SP::O4
, SP::O5
, SP::O6
, SP::O7
,
65 SP::L0
, SP::L1
, SP::L2
, SP::L3
,
66 SP::L4
, SP::L5
, SP::L6
, SP::L7
,
67 SP::I0
, SP::I1
, SP::I2
, SP::I3
,
68 SP::I4
, SP::I5
, SP::I6
, SP::I7
};
70 static const unsigned FPRegDecoderTable
[] = {
71 SP::F0
, SP::F1
, SP::F2
, SP::F3
,
72 SP::F4
, SP::F5
, SP::F6
, SP::F7
,
73 SP::F8
, SP::F9
, SP::F10
, SP::F11
,
74 SP::F12
, SP::F13
, SP::F14
, SP::F15
,
75 SP::F16
, SP::F17
, SP::F18
, SP::F19
,
76 SP::F20
, SP::F21
, SP::F22
, SP::F23
,
77 SP::F24
, SP::F25
, SP::F26
, SP::F27
,
78 SP::F28
, SP::F29
, SP::F30
, SP::F31
};
80 static const unsigned DFPRegDecoderTable
[] = {
81 SP::D0
, SP::D16
, SP::D1
, SP::D17
,
82 SP::D2
, SP::D18
, SP::D3
, SP::D19
,
83 SP::D4
, SP::D20
, SP::D5
, SP::D21
,
84 SP::D6
, SP::D22
, SP::D7
, SP::D23
,
85 SP::D8
, SP::D24
, SP::D9
, SP::D25
,
86 SP::D10
, SP::D26
, SP::D11
, SP::D27
,
87 SP::D12
, SP::D28
, SP::D13
, SP::D29
,
88 SP::D14
, SP::D30
, SP::D15
, SP::D31
};
90 static const unsigned QFPRegDecoderTable
[] = {
91 SP::Q0
, SP::Q8
, ~0U, ~0U,
92 SP::Q1
, SP::Q9
, ~0U, ~0U,
93 SP::Q2
, SP::Q10
, ~0U, ~0U,
94 SP::Q3
, SP::Q11
, ~0U, ~0U,
95 SP::Q4
, SP::Q12
, ~0U, ~0U,
96 SP::Q5
, SP::Q13
, ~0U, ~0U,
97 SP::Q6
, SP::Q14
, ~0U, ~0U,
98 SP::Q7
, SP::Q15
, ~0U, ~0U } ;
100 static const unsigned FCCRegDecoderTable
[] = {
101 SP::FCC0
, SP::FCC1
, SP::FCC2
, SP::FCC3
};
103 static const unsigned ASRRegDecoderTable
[] = {
104 SP::Y
, SP::ASR1
, SP::ASR2
, SP::ASR3
, SP::ASR4
, SP::ASR5
, SP::ASR6
,
105 SP::ASR7
, SP::ASR8
, SP::ASR9
, SP::ASR10
, SP::ASR11
, SP::ASR12
, SP::ASR13
,
106 SP::ASR14
, SP::ASR15
, SP::ASR16
, SP::ASR17
, SP::ASR18
, SP::ASR19
, SP::ASR20
,
107 SP::ASR21
, SP::ASR22
, SP::ASR23
, SP::ASR24
, SP::ASR25
, SP::ASR26
, SP::ASR27
,
108 SP::ASR28
, SP::ASR29
, SP::ASR30
, SP::ASR31
};
110 static const unsigned PRRegDecoderTable
[] = {
111 SP::TPC
, SP::TNPC
, SP::TSTATE
, SP::TT
, SP::TICK
,
112 SP::TBA
, SP::PSTATE
, SP::TL
, SP::PIL
, SP::CWP
,
113 SP::CANSAVE
, SP::CANRESTORE
, SP::CLEANWIN
, SP::OTHERWIN
, SP::WSTATE
};
115 static const uint16_t IntPairDecoderTable
[] = {
116 SP::G0_G1
, SP::G2_G3
, SP::G4_G5
, SP::G6_G7
,
117 SP::O0_O1
, SP::O2_O3
, SP::O4_O5
, SP::O6_O7
,
118 SP::L0_L1
, SP::L2_L3
, SP::L4_L5
, SP::L6_L7
,
119 SP::I0_I1
, SP::I2_I3
, SP::I4_I5
, SP::I6_I7
,
122 static const unsigned CPRegDecoderTable
[] = {
123 SP::C0
, SP::C1
, SP::C2
, SP::C3
,
124 SP::C4
, SP::C5
, SP::C6
, SP::C7
,
125 SP::C8
, SP::C9
, SP::C10
, SP::C11
,
126 SP::C12
, SP::C13
, SP::C14
, SP::C15
,
127 SP::C16
, SP::C17
, SP::C18
, SP::C19
,
128 SP::C20
, SP::C21
, SP::C22
, SP::C23
,
129 SP::C24
, SP::C25
, SP::C26
, SP::C27
,
130 SP::C28
, SP::C29
, SP::C30
, SP::C31
134 static const uint16_t CPPairDecoderTable
[] = {
135 SP::C0_C1
, SP::C2_C3
, SP::C4_C5
, SP::C6_C7
,
136 SP::C8_C9
, SP::C10_C11
, SP::C12_C13
, SP::C14_C15
,
137 SP::C16_C17
, SP::C18_C19
, SP::C20_C21
, SP::C22_C23
,
138 SP::C24_C25
, SP::C26_C27
, SP::C28_C29
, SP::C30_C31
141 static DecodeStatus
DecodeIntRegsRegisterClass(MCInst
&Inst
, unsigned RegNo
,
143 const MCDisassembler
*Decoder
) {
145 return MCDisassembler::Fail
;
146 unsigned Reg
= IntRegDecoderTable
[RegNo
];
147 Inst
.addOperand(MCOperand::createReg(Reg
));
148 return MCDisassembler::Success
;
151 static DecodeStatus
DecodeI64RegsRegisterClass(MCInst
&Inst
, unsigned RegNo
,
153 const MCDisassembler
*Decoder
) {
154 return DecodeIntRegsRegisterClass(Inst
, RegNo
, Address
, Decoder
);
157 // This is used for the type "ptr_rc", which is either IntRegs or I64Regs
158 // depending on SparcRegisterInfo::getPointerRegClass.
159 static DecodeStatus
DecodePointerLikeRegClass0(MCInst
&Inst
, unsigned RegNo
,
161 const MCDisassembler
*Decoder
) {
162 return DecodeIntRegsRegisterClass(Inst
, RegNo
, Address
, Decoder
);
165 static DecodeStatus
DecodeFPRegsRegisterClass(MCInst
&Inst
, unsigned RegNo
,
167 const MCDisassembler
*Decoder
) {
169 return MCDisassembler::Fail
;
170 unsigned Reg
= FPRegDecoderTable
[RegNo
];
171 Inst
.addOperand(MCOperand::createReg(Reg
));
172 return MCDisassembler::Success
;
175 static DecodeStatus
DecodeDFPRegsRegisterClass(MCInst
&Inst
, unsigned RegNo
,
177 const MCDisassembler
*Decoder
) {
179 return MCDisassembler::Fail
;
180 unsigned Reg
= DFPRegDecoderTable
[RegNo
];
181 Inst
.addOperand(MCOperand::createReg(Reg
));
182 return MCDisassembler::Success
;
185 static DecodeStatus
DecodeQFPRegsRegisterClass(MCInst
&Inst
, unsigned RegNo
,
187 const MCDisassembler
*Decoder
) {
189 return MCDisassembler::Fail
;
191 unsigned Reg
= QFPRegDecoderTable
[RegNo
];
193 return MCDisassembler::Fail
;
194 Inst
.addOperand(MCOperand::createReg(Reg
));
195 return MCDisassembler::Success
;
199 DecodeCoprocRegsRegisterClass(MCInst
&Inst
, unsigned RegNo
, uint64_t Address
,
200 const MCDisassembler
*Decoder
) {
202 return MCDisassembler::Fail
;
203 unsigned Reg
= CPRegDecoderTable
[RegNo
];
204 Inst
.addOperand(MCOperand::createReg(Reg
));
205 return MCDisassembler::Success
;
208 static DecodeStatus
DecodeFCCRegsRegisterClass(MCInst
&Inst
, unsigned RegNo
,
210 const MCDisassembler
*Decoder
) {
212 return MCDisassembler::Fail
;
213 Inst
.addOperand(MCOperand::createReg(FCCRegDecoderTable
[RegNo
]));
214 return MCDisassembler::Success
;
217 static DecodeStatus
DecodeASRRegsRegisterClass(MCInst
&Inst
, unsigned RegNo
,
219 const MCDisassembler
*Decoder
) {
221 return MCDisassembler::Fail
;
222 Inst
.addOperand(MCOperand::createReg(ASRRegDecoderTable
[RegNo
]));
223 return MCDisassembler::Success
;
226 static DecodeStatus
DecodePRRegsRegisterClass(MCInst
&Inst
, unsigned RegNo
,
228 const MCDisassembler
*Decoder
) {
229 if (RegNo
>= std::size(PRRegDecoderTable
))
230 return MCDisassembler::Fail
;
231 Inst
.addOperand(MCOperand::createReg(PRRegDecoderTable
[RegNo
]));
232 return MCDisassembler::Success
;
235 static DecodeStatus
DecodeIntPairRegisterClass(MCInst
&Inst
, unsigned RegNo
,
237 const MCDisassembler
*Decoder
) {
238 DecodeStatus S
= MCDisassembler::Success
;
241 return MCDisassembler::Fail
;
244 S
= MCDisassembler::SoftFail
;
246 unsigned RegisterPair
= IntPairDecoderTable
[RegNo
/2];
247 Inst
.addOperand(MCOperand::createReg(RegisterPair
));
252 DecodeCoprocPairRegisterClass(MCInst
&Inst
, unsigned RegNo
, uint64_t Address
,
253 const MCDisassembler
*Decoder
) {
255 return MCDisassembler::Fail
;
257 unsigned RegisterPair
= CPPairDecoderTable
[RegNo
/2];
258 Inst
.addOperand(MCOperand::createReg(RegisterPair
));
259 return MCDisassembler::Success
;
262 static DecodeStatus
DecodeCall(MCInst
&Inst
, unsigned insn
, uint64_t Address
,
263 const MCDisassembler
*Decoder
);
264 static DecodeStatus
DecodeSIMM13(MCInst
&Inst
, unsigned insn
, uint64_t Address
,
265 const MCDisassembler
*Decoder
);
267 #include "SparcGenDisassemblerTables.inc"
269 /// Read four bytes from the ArrayRef and return 32 bit word.
270 static DecodeStatus
readInstruction32(ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
271 uint64_t &Size
, uint32_t &Insn
,
272 bool IsLittleEndian
) {
273 // We want to read exactly 4 Bytes of data.
274 if (Bytes
.size() < 4) {
276 return MCDisassembler::Fail
;
279 Insn
= IsLittleEndian
280 ? (Bytes
[0] << 0) | (Bytes
[1] << 8) | (Bytes
[2] << 16) |
282 : (Bytes
[3] << 0) | (Bytes
[2] << 8) | (Bytes
[1] << 16) |
285 return MCDisassembler::Success
;
288 DecodeStatus
SparcDisassembler::getInstruction(MCInst
&Instr
, uint64_t &Size
,
289 ArrayRef
<uint8_t> Bytes
,
291 raw_ostream
&CStream
) const {
293 bool isLittleEndian
= getContext().getAsmInfo()->isLittleEndian();
294 DecodeStatus Result
=
295 readInstruction32(Bytes
, Address
, Size
, Insn
, isLittleEndian
);
296 if (Result
== MCDisassembler::Fail
)
297 return MCDisassembler::Fail
;
299 // Calling the auto-generated decoder function.
301 if (STI
.hasFeature(Sparc::FeatureV9
))
303 Result
= decodeInstruction(DecoderTableSparcV932
, Instr
, Insn
, Address
, this, STI
);
307 Result
= decodeInstruction(DecoderTableSparcV832
, Instr
, Insn
, Address
, this, STI
);
309 if (Result
!= MCDisassembler::Fail
) {
315 decodeInstruction(DecoderTableSparc32
, Instr
, Insn
, Address
, this, STI
);
317 if (Result
!= MCDisassembler::Fail
) {
322 return MCDisassembler::Fail
;
325 static bool tryAddingSymbolicOperand(int64_t Value
, bool isBranch
,
326 uint64_t Address
, uint64_t Offset
,
327 uint64_t Width
, MCInst
&MI
,
328 const MCDisassembler
*Decoder
) {
329 return Decoder
->tryAddingSymbolicOperand(MI
, Value
, Address
, isBranch
, Offset
,
330 Width
, /*InstSize=*/4);
333 static DecodeStatus
DecodeCall(MCInst
&MI
, unsigned insn
, uint64_t Address
,
334 const MCDisassembler
*Decoder
) {
335 unsigned tgt
= fieldFromInstruction(insn
, 0, 30);
337 if (!tryAddingSymbolicOperand(tgt
+Address
, false, Address
,
339 MI
.addOperand(MCOperand::createImm(tgt
));
340 return MCDisassembler::Success
;
343 static DecodeStatus
DecodeSIMM13(MCInst
&MI
, unsigned insn
, uint64_t Address
,
344 const MCDisassembler
*Decoder
) {
345 assert(isUInt
<13>(insn
));
346 MI
.addOperand(MCOperand::createImm(SignExtend64
<13>(insn
)));
347 return MCDisassembler::Success
;