/src/capstonenext/arch/Sparc/SparcDisassembler.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Capstone Disassembly Engine, http://www.capstone-engine.org */ |
2 | | /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */ |
3 | | /* Rot127 <unisono@quyllur.org> 2022-2023 */ |
4 | | /* Automatically translated source file from LLVM. */ |
5 | | |
6 | | /* LLVM-commit: <commit> */ |
7 | | /* LLVM-tag: <tag> */ |
8 | | |
9 | | /* Only small edits allowed. */ |
10 | | /* For multiple similar edits, please create a Patch for the translator. */ |
11 | | |
12 | | /* Capstone's C++ file translator: */ |
13 | | /* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */ |
14 | | |
15 | | //===- SparcDisassembler.cpp - Disassembler for Sparc -----------*- C++ -*-===// |
16 | | // |
17 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
18 | | // See https://llvm.org/LICENSE.txt for license information. |
19 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
20 | | // |
21 | | //===----------------------------------------------------------------------===// |
22 | | // |
23 | | // This file is part of the Sparc Disassembler. |
24 | | // |
25 | | //===----------------------------------------------------------------------===// |
26 | | |
27 | | #include <stdio.h> |
28 | | #include <string.h> |
29 | | #include <stdlib.h> |
30 | | #include <capstone/platform.h> |
31 | | |
32 | | #include "../../MCDisassembler.h" |
33 | | #include "../../MCFixedLenDisassembler.h" |
34 | | #include "SparcDisassemblerExtension.h" |
35 | | #include "SparcLinkage.h" |
36 | | #include "SparcMapping.h" |
37 | | #include "SparcMCTargetDesc.h" |
38 | | #define CONCAT(a, b) CONCAT_(a, b) |
39 | | #define CONCAT_(a, b) a##_##b |
40 | | |
41 | | #define DEBUG_TYPE "sparc-disassembler" |
42 | | |
43 | | static const unsigned IntRegDecoderTable[] = { |
44 | | Sparc_G0, Sparc_G1, Sparc_G2, Sparc_G3, Sparc_G4, Sparc_G5, Sparc_G6, Sparc_G7, |
45 | | Sparc_O0, Sparc_O1, Sparc_O2, Sparc_O3, Sparc_O4, Sparc_O5, Sparc_O6, Sparc_O7, |
46 | | Sparc_L0, Sparc_L1, Sparc_L2, Sparc_L3, Sparc_L4, Sparc_L5, Sparc_L6, Sparc_L7, |
47 | | Sparc_I0, Sparc_I1, Sparc_I2, Sparc_I3, Sparc_I4, Sparc_I5, Sparc_I6, Sparc_I7 |
48 | | }; |
49 | | |
50 | | static const unsigned FPRegDecoderTable[] = { |
51 | | Sparc_F0, Sparc_F1, Sparc_F2, Sparc_F3, Sparc_F4, Sparc_F5, Sparc_F6, Sparc_F7, |
52 | | Sparc_F8, Sparc_F9, Sparc_F10, Sparc_F11, Sparc_F12, Sparc_F13, Sparc_F14, Sparc_F15, |
53 | | Sparc_F16, Sparc_F17, Sparc_F18, Sparc_F19, Sparc_F20, Sparc_F21, Sparc_F22, Sparc_F23, |
54 | | Sparc_F24, Sparc_F25, Sparc_F26, Sparc_F27, Sparc_F28, Sparc_F29, Sparc_F30, Sparc_F31 |
55 | | }; |
56 | | |
57 | | static const unsigned DFPRegDecoderTable[] = { |
58 | | Sparc_D0, Sparc_D16, Sparc_D1, Sparc_D17, Sparc_D2, Sparc_D18, Sparc_D3, Sparc_D19, |
59 | | Sparc_D4, Sparc_D20, Sparc_D5, Sparc_D21, Sparc_D6, Sparc_D22, Sparc_D7, Sparc_D23, |
60 | | Sparc_D8, Sparc_D24, Sparc_D9, Sparc_D25, Sparc_D10, Sparc_D26, Sparc_D11, Sparc_D27, |
61 | | Sparc_D12, Sparc_D28, Sparc_D13, Sparc_D29, Sparc_D14, Sparc_D30, Sparc_D15, Sparc_D31 |
62 | | }; |
63 | | |
64 | | static const unsigned QFPRegDecoderTable[] = { |
65 | | Sparc_Q0, Sparc_Q8, ~0U, ~0U, Sparc_Q1, Sparc_Q9, ~0U, ~0U, |
66 | | Sparc_Q2, Sparc_Q10, ~0U, ~0U, Sparc_Q3, Sparc_Q11, ~0U, ~0U, |
67 | | Sparc_Q4, Sparc_Q12, ~0U, ~0U, Sparc_Q5, Sparc_Q13, ~0U, ~0U, |
68 | | Sparc_Q6, Sparc_Q14, ~0U, ~0U, Sparc_Q7, Sparc_Q15, ~0U, ~0U |
69 | | }; |
70 | | |
71 | | static const unsigned FCCRegDecoderTable[] = { Sparc_FCC0, Sparc_FCC1, Sparc_FCC2, |
72 | | Sparc_FCC3 }; |
73 | | |
74 | | static const unsigned ASRRegDecoderTable[] = { |
75 | | Sparc_Y, Sparc_ASR1, Sparc_ASR2, Sparc_ASR3, Sparc_ASR4, Sparc_ASR5, Sparc_ASR6, |
76 | | Sparc_ASR7, Sparc_ASR8, Sparc_ASR9, Sparc_ASR10, Sparc_ASR11, Sparc_ASR12, Sparc_ASR13, |
77 | | Sparc_ASR14, Sparc_ASR15, Sparc_ASR16, Sparc_ASR17, Sparc_ASR18, Sparc_ASR19, Sparc_ASR20, |
78 | | Sparc_ASR21, Sparc_ASR22, Sparc_ASR23, Sparc_ASR24, Sparc_ASR25, Sparc_ASR26, Sparc_ASR27, |
79 | | Sparc_ASR28, Sparc_ASR29, Sparc_ASR30, Sparc_ASR31 |
80 | | }; |
81 | | |
82 | | static const unsigned PRRegDecoderTable[] = { |
83 | | Sparc_TPC, Sparc_TNPC, Sparc_TSTATE, Sparc_TT, Sparc_TICK, |
84 | | Sparc_TBA, Sparc_PSTATE, Sparc_TL, Sparc_PIL, Sparc_CWP, |
85 | | Sparc_CANSAVE, Sparc_CANRESTORE, Sparc_CLEANWIN, Sparc_OTHERWIN, Sparc_WSTATE |
86 | | }; |
87 | | |
88 | | static const uint16_t IntPairDecoderTable[] = { |
89 | | Sparc_G0_G1, Sparc_G2_G3, Sparc_G4_G5, Sparc_G6_G7, Sparc_O0_O1, Sparc_O2_O3, |
90 | | Sparc_O4_O5, Sparc_O6_O7, Sparc_L0_L1, Sparc_L2_L3, Sparc_L4_L5, Sparc_L6_L7, |
91 | | Sparc_I0_I1, Sparc_I2_I3, Sparc_I4_I5, Sparc_I6_I7, |
92 | | }; |
93 | | |
94 | | static const unsigned CPRegDecoderTable[] = { |
95 | | Sparc_C0, Sparc_C1, Sparc_C2, Sparc_C3, Sparc_C4, Sparc_C5, Sparc_C6, Sparc_C7, |
96 | | Sparc_C8, Sparc_C9, Sparc_C10, Sparc_C11, Sparc_C12, Sparc_C13, Sparc_C14, Sparc_C15, |
97 | | Sparc_C16, Sparc_C17, Sparc_C18, Sparc_C19, Sparc_C20, Sparc_C21, Sparc_C22, Sparc_C23, |
98 | | Sparc_C24, Sparc_C25, Sparc_C26, Sparc_C27, Sparc_C28, Sparc_C29, Sparc_C30, Sparc_C31 |
99 | | }; |
100 | | |
101 | | static const uint16_t CPPairDecoderTable[] = { |
102 | | Sparc_C0_C1, Sparc_C2_C3, Sparc_C4_C5, Sparc_C6_C7, Sparc_C8_C9, Sparc_C10_C11, |
103 | | Sparc_C12_C13, Sparc_C14_C15, Sparc_C16_C17, Sparc_C18_C19, Sparc_C20_C21, Sparc_C22_C23, |
104 | | Sparc_C24_C25, Sparc_C26_C27, Sparc_C28_C29, Sparc_C30_C31 |
105 | | }; |
106 | | |
107 | | static DecodeStatus DecodeDisp19(MCInst *Inst, uint32_t ImmVal, |
108 | | uint64_t Address, |
109 | | const void *Decoder) |
110 | 4.16k | { |
111 | 4.16k | int64_t BranchTarget = Address + (SignExtend64(ImmVal, 19) * 4); |
112 | 4.16k | MCOperand_CreateImm0(Inst, BranchTarget); |
113 | 4.16k | return MCDisassembler_Success; |
114 | 4.16k | } |
115 | | |
116 | | static DecodeStatus DecodeDisp16(MCInst *Inst, uint32_t ImmVal, |
117 | | uint64_t Address, |
118 | | const void *Decoder) |
119 | 975 | { |
120 | 975 | int64_t BranchTarget = Address + (SignExtend64(ImmVal, 16) * 4); |
121 | 975 | MCOperand_CreateImm0(Inst, BranchTarget); |
122 | 975 | return MCDisassembler_Success; |
123 | 975 | } |
124 | | |
125 | | static DecodeStatus DecodeDisp22(MCInst *Inst, uint32_t ImmVal, |
126 | | uint64_t Address, |
127 | | const void *Decoder) |
128 | 1.71k | { |
129 | 1.71k | int64_t BranchTarget = Address + (SignExtend64(ImmVal, 22) * 4); |
130 | 1.71k | MCOperand_CreateImm0(Inst, BranchTarget); |
131 | 1.71k | return MCDisassembler_Success; |
132 | 1.71k | } |
133 | | |
134 | | static DecodeStatus DecodeIntRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
135 | | uint64_t Address, |
136 | | const void *Decoder) |
137 | 23.0k | { |
138 | 23.0k | if (RegNo > 31) |
139 | 0 | return MCDisassembler_Fail; |
140 | 23.0k | unsigned Reg = IntRegDecoderTable[RegNo]; |
141 | 23.0k | MCOperand_CreateReg0(Inst, (Reg)); |
142 | 23.0k | return MCDisassembler_Success; |
143 | 23.0k | } |
144 | | |
145 | | static DecodeStatus DecodeI64RegsRegisterClass(MCInst *Inst, unsigned RegNo, |
146 | | uint64_t Address, |
147 | | const void *Decoder) |
148 | 3.85k | { |
149 | 3.85k | return DecodeIntRegsRegisterClass(Inst, RegNo, Address, Decoder); |
150 | 3.85k | } |
151 | | |
152 | | // This is used for the type "ptr_rc", which is either IntRegs or I64Regs |
153 | | // depending on SparcRegisterInfo::getPointerRegClass. |
154 | | static DecodeStatus DecodePointerLikeRegClass0(MCInst *Inst, unsigned RegNo, |
155 | | uint64_t Address, |
156 | | const void *Decoder) |
157 | 7.87k | { |
158 | 7.87k | return DecodeIntRegsRegisterClass(Inst, RegNo, Address, Decoder); |
159 | 7.87k | } |
160 | | |
161 | | static DecodeStatus DecodeFPRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
162 | | uint64_t Address, |
163 | | const void *Decoder) |
164 | 1.66k | { |
165 | 1.66k | if (RegNo > 31) |
166 | 0 | return MCDisassembler_Fail; |
167 | 1.66k | unsigned Reg = FPRegDecoderTable[RegNo]; |
168 | 1.66k | MCOperand_CreateReg0(Inst, (Reg)); |
169 | 1.66k | return MCDisassembler_Success; |
170 | 1.66k | } |
171 | | |
172 | | static DecodeStatus DecodeDFPRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
173 | | uint64_t Address, |
174 | | const void *Decoder) |
175 | 1.71k | { |
176 | 1.71k | if (RegNo > 31) |
177 | 0 | return MCDisassembler_Fail; |
178 | 1.71k | unsigned Reg = DFPRegDecoderTable[RegNo]; |
179 | 1.71k | MCOperand_CreateReg0(Inst, (Reg)); |
180 | 1.71k | return MCDisassembler_Success; |
181 | 1.71k | } |
182 | | |
183 | | static DecodeStatus DecodeQFPRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
184 | | uint64_t Address, |
185 | | const void *Decoder) |
186 | 554 | { |
187 | 554 | if (RegNo > 31) |
188 | 0 | return MCDisassembler_Fail; |
189 | | |
190 | 554 | unsigned Reg = QFPRegDecoderTable[RegNo]; |
191 | 554 | if (Reg == ~0U) |
192 | 21 | return MCDisassembler_Fail; |
193 | 533 | MCOperand_CreateReg0(Inst, (Reg)); |
194 | 533 | return MCDisassembler_Success; |
195 | 554 | } |
196 | | |
197 | | static DecodeStatus DecodeCoprocRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
198 | | uint64_t Address, |
199 | | const void *Decoder) |
200 | 27 | { |
201 | 27 | if (RegNo > 31) |
202 | 0 | return MCDisassembler_Fail; |
203 | 27 | unsigned Reg = CPRegDecoderTable[RegNo]; |
204 | 27 | MCOperand_CreateReg0(Inst, (Reg)); |
205 | 27 | return MCDisassembler_Success; |
206 | 27 | } |
207 | | |
208 | | static DecodeStatus DecodeFCCRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
209 | | uint64_t Address, |
210 | | const void *Decoder) |
211 | 2.18k | { |
212 | 2.18k | if (RegNo > 3) |
213 | 3 | return MCDisassembler_Fail; |
214 | 2.18k | MCOperand_CreateReg0(Inst, (FCCRegDecoderTable[RegNo])); |
215 | 2.18k | return MCDisassembler_Success; |
216 | 2.18k | } |
217 | | |
218 | | static DecodeStatus DecodeASRRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
219 | | uint64_t Address, |
220 | | const void *Decoder) |
221 | 51 | { |
222 | 51 | if (RegNo > 31) |
223 | 0 | return MCDisassembler_Fail; |
224 | 51 | MCOperand_CreateReg0(Inst, (ASRRegDecoderTable[RegNo])); |
225 | 51 | return MCDisassembler_Success; |
226 | 51 | } |
227 | | |
228 | | static DecodeStatus DecodePRRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
229 | | uint64_t Address, |
230 | | const void *Decoder) |
231 | 18 | { |
232 | 18 | if (RegNo >= ARR_SIZE(PRRegDecoderTable)) |
233 | 3 | return MCDisassembler_Fail; |
234 | 15 | MCOperand_CreateReg0(Inst, (PRRegDecoderTable[RegNo])); |
235 | 15 | return MCDisassembler_Success; |
236 | 18 | } |
237 | | |
238 | | static DecodeStatus DecodeIntPairRegisterClass(MCInst *Inst, unsigned RegNo, |
239 | | uint64_t Address, |
240 | | const void *Decoder) |
241 | 166 | { |
242 | 166 | DecodeStatus S = MCDisassembler_Success; |
243 | | |
244 | 166 | if (RegNo > 31) |
245 | 0 | return MCDisassembler_Fail; |
246 | | |
247 | 166 | if ((RegNo & 1)) |
248 | 80 | S = MCDisassembler_SoftFail; |
249 | | |
250 | 166 | unsigned RegisterPair = IntPairDecoderTable[RegNo / 2]; |
251 | 166 | MCOperand_CreateReg0(Inst, (RegisterPair)); |
252 | 166 | return S; |
253 | 166 | } |
254 | | |
255 | | static DecodeStatus DecodeCoprocPairRegisterClass(MCInst *Inst, unsigned RegNo, |
256 | | uint64_t Address, |
257 | | const void *Decoder) |
258 | 25 | { |
259 | 25 | if (RegNo > 31) |
260 | 0 | return MCDisassembler_Fail; |
261 | | |
262 | 25 | unsigned RegisterPair = CPPairDecoderTable[RegNo / 2]; |
263 | 25 | MCOperand_CreateReg0(Inst, (RegisterPair)); |
264 | 25 | return MCDisassembler_Success; |
265 | 25 | } |
266 | | |
267 | | static DecodeStatus DecodeCall(MCInst *Inst, unsigned insn, uint64_t Address, |
268 | | const void *Decoder); |
269 | | static DecodeStatus DecodeSIMM13(MCInst *Inst, unsigned insn, uint64_t Address, |
270 | | const void *Decoder); |
271 | | |
272 | | #include "SparcGenDisassemblerTables.inc" |
273 | | |
274 | | static DecodeStatus getInstruction(MCInst *Instr, uint64_t *Size, const uint8_t *Bytes, |
275 | | size_t BytesLen, uint64_t Address, SStream *CStream) |
276 | 27.8k | { |
277 | 27.8k | if (BytesLen < 4) { |
278 | 369 | return MCDisassembler_Fail; |
279 | 369 | } |
280 | 27.5k | uint32_t Insn = readBytes32(Instr, Bytes); |
281 | | |
282 | 27.5k | DecodeStatus Result = MCDisassembler_Fail; |
283 | | // Calling the auto-generated decoder function. |
284 | 27.5k | if (Sparc_getFeatureBits(Instr->csh->mode, Sparc_FeatureV9)) { |
285 | 24.8k | Result = decodeInstruction_4(DecoderTableSparcV932, Instr, Insn, |
286 | 24.8k | Address, NULL); |
287 | 24.8k | } else { |
288 | 2.61k | Result = decodeInstruction_4(DecoderTableSparcV832, Instr, Insn, |
289 | 2.61k | Address, NULL); |
290 | 2.61k | } |
291 | 27.5k | if (Result != MCDisassembler_Fail) { |
292 | 273 | *Size = 4; |
293 | 273 | return Result; |
294 | 273 | } |
295 | | |
296 | 27.2k | Result = decodeInstruction_4(DecoderTableSparc32, Instr, Insn, Address, |
297 | 27.2k | NULL); |
298 | | |
299 | 27.2k | if (Result != MCDisassembler_Fail) { |
300 | 27.0k | *Size = 4; |
301 | 27.0k | return Result; |
302 | 27.0k | } |
303 | | |
304 | 183 | return MCDisassembler_Fail; |
305 | 27.2k | } |
306 | | |
307 | | static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch, |
308 | | uint64_t Address, uint64_t Offset, |
309 | | uint64_t Width, MCInst *MI, |
310 | | const void *Decoder) |
311 | 4.73k | { |
312 | | // Capstone doesn't support symbols. |
313 | 4.73k | return false; |
314 | 4.73k | } |
315 | | |
316 | | static DecodeStatus DecodeCall(MCInst *MI, unsigned insn, uint64_t Address, |
317 | | const void *Decoder) |
318 | 4.73k | { |
319 | 4.73k | unsigned Offset = fieldFromInstruction_4(insn, 0, 30); |
320 | 4.73k | int64_t CallTarget = Address + (SignExtend64(Offset, 30) * 4); |
321 | 4.73k | if (!tryAddingSymbolicOperand(CallTarget, false, Address, 0, 30, MI, |
322 | 4.73k | Decoder)) |
323 | 4.73k | MCOperand_CreateImm0(MI, CallTarget); |
324 | 4.73k | return MCDisassembler_Success; |
325 | 4.73k | } |
326 | | |
327 | | static DecodeStatus DecodeSIMM13(MCInst *MI, unsigned insn, uint64_t Address, |
328 | | const void *Decoder) |
329 | 1.05k | { |
330 | 1.05k | CS_ASSERT(isUIntN(13, insn)); |
331 | 1.05k | MCOperand_CreateImm0(MI, (SignExtend64((insn), 13))); |
332 | 1.05k | return MCDisassembler_Success; |
333 | 1.05k | } |
334 | | |
335 | | DecodeStatus Sparc_LLVM_getInstruction(csh handle, const uint8_t *Bytes, |
336 | | size_t ByteLen, MCInst *MI, uint16_t *Size, |
337 | 27.8k | uint64_t Address, void *Info) { |
338 | 27.8k | uint64_t s = 0; |
339 | 27.8k | DecodeStatus status = getInstruction(MI, &s, Bytes, ByteLen, Address, NULL); |
340 | 27.8k | *Size = (uint16_t) s; |
341 | 27.8k | return status; |
342 | 27.8k | } |