/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, |
45 | | Sparc_G7, Sparc_O0, Sparc_O1, Sparc_O2, Sparc_O3, Sparc_O4, Sparc_O5, |
46 | | Sparc_O6, Sparc_O7, Sparc_L0, Sparc_L1, Sparc_L2, Sparc_L3, Sparc_L4, |
47 | | Sparc_L5, Sparc_L6, Sparc_L7, Sparc_I0, Sparc_I1, Sparc_I2, Sparc_I3, |
48 | | Sparc_I4, Sparc_I5, Sparc_I6, Sparc_I7 |
49 | | }; |
50 | | |
51 | | static const unsigned FPRegDecoderTable[] = { |
52 | | Sparc_F0, Sparc_F1, Sparc_F2, Sparc_F3, Sparc_F4, Sparc_F5, |
53 | | Sparc_F6, Sparc_F7, Sparc_F8, Sparc_F9, Sparc_F10, Sparc_F11, |
54 | | Sparc_F12, Sparc_F13, Sparc_F14, Sparc_F15, Sparc_F16, Sparc_F17, |
55 | | Sparc_F18, Sparc_F19, Sparc_F20, Sparc_F21, Sparc_F22, Sparc_F23, |
56 | | Sparc_F24, Sparc_F25, Sparc_F26, Sparc_F27, Sparc_F28, Sparc_F29, |
57 | | Sparc_F30, Sparc_F31 |
58 | | }; |
59 | | |
60 | | static const unsigned DFPRegDecoderTable[] = { |
61 | | Sparc_D0, Sparc_D16, Sparc_D1, Sparc_D17, Sparc_D2, Sparc_D18, |
62 | | Sparc_D3, Sparc_D19, Sparc_D4, Sparc_D20, Sparc_D5, Sparc_D21, |
63 | | Sparc_D6, Sparc_D22, Sparc_D7, Sparc_D23, Sparc_D8, Sparc_D24, |
64 | | Sparc_D9, Sparc_D25, Sparc_D10, Sparc_D26, Sparc_D11, Sparc_D27, |
65 | | Sparc_D12, Sparc_D28, Sparc_D13, Sparc_D29, Sparc_D14, Sparc_D30, |
66 | | Sparc_D15, Sparc_D31 |
67 | | }; |
68 | | |
69 | | static const unsigned QFPRegDecoderTable[] = { |
70 | | Sparc_Q0, Sparc_Q8, ~0U, ~0U, Sparc_Q1, Sparc_Q9, ~0U, ~0U, |
71 | | Sparc_Q2, Sparc_Q10, ~0U, ~0U, Sparc_Q3, Sparc_Q11, ~0U, ~0U, |
72 | | Sparc_Q4, Sparc_Q12, ~0U, ~0U, Sparc_Q5, Sparc_Q13, ~0U, ~0U, |
73 | | Sparc_Q6, Sparc_Q14, ~0U, ~0U, Sparc_Q7, Sparc_Q15, ~0U, ~0U |
74 | | }; |
75 | | |
76 | | static const unsigned FCCRegDecoderTable[] = { Sparc_FCC0, Sparc_FCC1, |
77 | | Sparc_FCC2, Sparc_FCC3 }; |
78 | | |
79 | | static const unsigned ASRRegDecoderTable[] = { |
80 | | Sparc_Y, Sparc_ASR1, Sparc_ASR2, Sparc_ASR3, Sparc_ASR4, |
81 | | Sparc_ASR5, Sparc_ASR6, Sparc_ASR7, Sparc_ASR8, Sparc_ASR9, |
82 | | Sparc_ASR10, Sparc_ASR11, Sparc_ASR12, Sparc_ASR13, Sparc_ASR14, |
83 | | Sparc_ASR15, Sparc_ASR16, Sparc_ASR17, Sparc_ASR18, Sparc_ASR19, |
84 | | Sparc_ASR20, Sparc_ASR21, Sparc_ASR22, Sparc_ASR23, Sparc_ASR24, |
85 | | Sparc_ASR25, Sparc_ASR26, Sparc_ASR27, Sparc_ASR28, Sparc_ASR29, |
86 | | Sparc_ASR30, Sparc_ASR31 |
87 | | }; |
88 | | |
89 | | static const unsigned PRRegDecoderTable[] = { |
90 | | Sparc_TPC, Sparc_TNPC, Sparc_TSTATE, Sparc_TT, |
91 | | Sparc_TICK, Sparc_TBA, Sparc_PSTATE, Sparc_TL, |
92 | | Sparc_PIL, Sparc_CWP, Sparc_CANSAVE, Sparc_CANRESTORE, |
93 | | Sparc_CLEANWIN, Sparc_OTHERWIN, Sparc_WSTATE |
94 | | }; |
95 | | |
96 | | static const uint16_t IntPairDecoderTable[] = { |
97 | | Sparc_G0_G1, Sparc_G2_G3, Sparc_G4_G5, Sparc_G6_G7, |
98 | | Sparc_O0_O1, Sparc_O2_O3, Sparc_O4_O5, Sparc_O6_O7, |
99 | | Sparc_L0_L1, Sparc_L2_L3, Sparc_L4_L5, Sparc_L6_L7, |
100 | | Sparc_I0_I1, Sparc_I2_I3, Sparc_I4_I5, Sparc_I6_I7, |
101 | | }; |
102 | | |
103 | | static const unsigned CPRegDecoderTable[] = { |
104 | | Sparc_C0, Sparc_C1, Sparc_C2, Sparc_C3, Sparc_C4, Sparc_C5, |
105 | | Sparc_C6, Sparc_C7, Sparc_C8, Sparc_C9, Sparc_C10, Sparc_C11, |
106 | | Sparc_C12, Sparc_C13, Sparc_C14, Sparc_C15, Sparc_C16, Sparc_C17, |
107 | | Sparc_C18, Sparc_C19, Sparc_C20, Sparc_C21, Sparc_C22, Sparc_C23, |
108 | | Sparc_C24, Sparc_C25, Sparc_C26, Sparc_C27, Sparc_C28, Sparc_C29, |
109 | | Sparc_C30, Sparc_C31 |
110 | | }; |
111 | | |
112 | | static const uint16_t CPPairDecoderTable[] = { |
113 | | Sparc_C0_C1, Sparc_C2_C3, Sparc_C4_C5, Sparc_C6_C7, |
114 | | Sparc_C8_C9, Sparc_C10_C11, Sparc_C12_C13, Sparc_C14_C15, |
115 | | Sparc_C16_C17, Sparc_C18_C19, Sparc_C20_C21, Sparc_C22_C23, |
116 | | Sparc_C24_C25, Sparc_C26_C27, Sparc_C28_C29, Sparc_C30_C31 |
117 | | }; |
118 | | |
119 | | static DecodeStatus DecodeDisp19(MCInst *Inst, uint32_t ImmVal, |
120 | | uint64_t Address, const void *Decoder) |
121 | 7.04k | { |
122 | 7.04k | int64_t BranchTarget = Address + (SignExtend64(ImmVal, 19) * 4); |
123 | 7.04k | MCOperand_CreateImm0(Inst, BranchTarget); |
124 | 7.04k | return MCDisassembler_Success; |
125 | 7.04k | } |
126 | | |
127 | | static DecodeStatus DecodeDisp16(MCInst *Inst, uint32_t ImmVal, |
128 | | uint64_t Address, const void *Decoder) |
129 | 1.68k | { |
130 | 1.68k | int64_t BranchTarget = Address + (SignExtend64(ImmVal, 16) * 4); |
131 | 1.68k | MCOperand_CreateImm0(Inst, BranchTarget); |
132 | 1.68k | return MCDisassembler_Success; |
133 | 1.68k | } |
134 | | |
135 | | static DecodeStatus DecodeDisp22(MCInst *Inst, uint32_t ImmVal, |
136 | | uint64_t Address, const void *Decoder) |
137 | 6.03k | { |
138 | 6.03k | int64_t BranchTarget = Address + (SignExtend64(ImmVal, 22) * 4); |
139 | 6.03k | MCOperand_CreateImm0(Inst, BranchTarget); |
140 | 6.03k | return MCDisassembler_Success; |
141 | 6.03k | } |
142 | | |
143 | | static DecodeStatus DecodeIntRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
144 | | uint64_t Address, |
145 | | const void *Decoder) |
146 | 83.7k | { |
147 | 83.7k | if (RegNo > 31) |
148 | 0 | return MCDisassembler_Fail; |
149 | 83.7k | unsigned Reg = IntRegDecoderTable[RegNo]; |
150 | 83.7k | MCOperand_CreateReg0(Inst, (Reg)); |
151 | 83.7k | return MCDisassembler_Success; |
152 | 83.7k | } |
153 | | |
154 | | static DecodeStatus DecodeI64RegsRegisterClass(MCInst *Inst, unsigned RegNo, |
155 | | uint64_t Address, |
156 | | const void *Decoder) |
157 | 6.09k | { |
158 | 6.09k | return DecodeIntRegsRegisterClass(Inst, RegNo, Address, Decoder); |
159 | 6.09k | } |
160 | | |
161 | | // This is used for the type "ptr_rc", which is either IntRegs or I64Regs |
162 | | // depending on SparcRegisterInfo::getPointerRegClass. |
163 | | static DecodeStatus DecodePointerLikeRegClass0(MCInst *Inst, unsigned RegNo, |
164 | | uint64_t Address, |
165 | | const void *Decoder) |
166 | 18.1k | { |
167 | 18.1k | return DecodeIntRegsRegisterClass(Inst, RegNo, Address, Decoder); |
168 | 18.1k | } |
169 | | |
170 | | static DecodeStatus DecodeFPRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
171 | | uint64_t Address, |
172 | | const void *Decoder) |
173 | 10.2k | { |
174 | 10.2k | if (RegNo > 31) |
175 | 0 | return MCDisassembler_Fail; |
176 | 10.2k | unsigned Reg = FPRegDecoderTable[RegNo]; |
177 | 10.2k | MCOperand_CreateReg0(Inst, (Reg)); |
178 | 10.2k | return MCDisassembler_Success; |
179 | 10.2k | } |
180 | | |
181 | | static DecodeStatus DecodeDFPRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
182 | | uint64_t Address, |
183 | | const void *Decoder) |
184 | 7.36k | { |
185 | 7.36k | if (RegNo > 31) |
186 | 0 | return MCDisassembler_Fail; |
187 | 7.36k | unsigned Reg = DFPRegDecoderTable[RegNo]; |
188 | 7.36k | MCOperand_CreateReg0(Inst, (Reg)); |
189 | 7.36k | return MCDisassembler_Success; |
190 | 7.36k | } |
191 | | |
192 | | static DecodeStatus DecodeQFPRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
193 | | uint64_t Address, |
194 | | const void *Decoder) |
195 | 8.32k | { |
196 | 8.32k | if (RegNo > 31) |
197 | 0 | return MCDisassembler_Fail; |
198 | | |
199 | 8.32k | unsigned Reg = QFPRegDecoderTable[RegNo]; |
200 | 8.32k | if (Reg == ~0U) |
201 | 47 | return MCDisassembler_Fail; |
202 | 8.28k | MCOperand_CreateReg0(Inst, (Reg)); |
203 | 8.28k | return MCDisassembler_Success; |
204 | 8.32k | } |
205 | | |
206 | | static DecodeStatus DecodeCoprocRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
207 | | uint64_t Address, |
208 | | const void *Decoder) |
209 | 352 | { |
210 | 352 | if (RegNo > 31) |
211 | 0 | return MCDisassembler_Fail; |
212 | 352 | unsigned Reg = CPRegDecoderTable[RegNo]; |
213 | 352 | MCOperand_CreateReg0(Inst, (Reg)); |
214 | 352 | return MCDisassembler_Success; |
215 | 352 | } |
216 | | |
217 | | static DecodeStatus DecodeFCCRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
218 | | uint64_t Address, |
219 | | const void *Decoder) |
220 | 15.5k | { |
221 | 15.5k | if (RegNo > 3) |
222 | 7 | return MCDisassembler_Fail; |
223 | 15.5k | MCOperand_CreateReg0(Inst, (FCCRegDecoderTable[RegNo])); |
224 | 15.5k | return MCDisassembler_Success; |
225 | 15.5k | } |
226 | | |
227 | | static DecodeStatus DecodeASRRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
228 | | uint64_t Address, |
229 | | const void *Decoder) |
230 | 302 | { |
231 | 302 | if (RegNo > 31) |
232 | 0 | return MCDisassembler_Fail; |
233 | 302 | MCOperand_CreateReg0(Inst, (ASRRegDecoderTable[RegNo])); |
234 | 302 | return MCDisassembler_Success; |
235 | 302 | } |
236 | | |
237 | | static DecodeStatus DecodePRRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
238 | | uint64_t Address, |
239 | | const void *Decoder) |
240 | 126 | { |
241 | 126 | if (RegNo >= ARR_SIZE(PRRegDecoderTable)) |
242 | 4 | return MCDisassembler_Fail; |
243 | 122 | MCOperand_CreateReg0(Inst, (PRRegDecoderTable[RegNo])); |
244 | 122 | return MCDisassembler_Success; |
245 | 126 | } |
246 | | |
247 | | static DecodeStatus DecodeIntPairRegisterClass(MCInst *Inst, unsigned RegNo, |
248 | | uint64_t Address, |
249 | | const void *Decoder) |
250 | 1.38k | { |
251 | 1.38k | DecodeStatus S = MCDisassembler_Success; |
252 | | |
253 | 1.38k | if (RegNo > 31) |
254 | 0 | return MCDisassembler_Fail; |
255 | | |
256 | 1.38k | if ((RegNo & 1)) |
257 | 566 | S = MCDisassembler_SoftFail; |
258 | | |
259 | 1.38k | unsigned RegisterPair = IntPairDecoderTable[RegNo / 2]; |
260 | 1.38k | MCOperand_CreateReg0(Inst, (RegisterPair)); |
261 | 1.38k | return S; |
262 | 1.38k | } |
263 | | |
264 | | static DecodeStatus DecodeCoprocPairRegisterClass(MCInst *Inst, unsigned RegNo, |
265 | | uint64_t Address, |
266 | | const void *Decoder) |
267 | 164 | { |
268 | 164 | if (RegNo > 31) |
269 | 0 | return MCDisassembler_Fail; |
270 | | |
271 | 164 | unsigned RegisterPair = CPPairDecoderTable[RegNo / 2]; |
272 | 164 | MCOperand_CreateReg0(Inst, (RegisterPair)); |
273 | 164 | return MCDisassembler_Success; |
274 | 164 | } |
275 | | |
276 | | static DecodeStatus DecodeCall(MCInst *Inst, unsigned insn, uint64_t Address, |
277 | | const void *Decoder); |
278 | | static DecodeStatus DecodeSIMM13(MCInst *Inst, unsigned insn, uint64_t Address, |
279 | | const void *Decoder); |
280 | | |
281 | | #include "SparcGenDisassemblerTables.inc" |
282 | | |
283 | | static DecodeStatus getInstruction(MCInst *Instr, uint64_t *Size, |
284 | | const uint8_t *Bytes, size_t BytesLen, |
285 | | uint64_t Address, SStream *CStream) |
286 | 48.2k | { |
287 | 48.2k | if (BytesLen < 4) { |
288 | 646 | return MCDisassembler_Fail; |
289 | 646 | } |
290 | 47.5k | uint32_t Insn = readBytes32(Instr, Bytes); |
291 | | |
292 | 47.5k | DecodeStatus Result = MCDisassembler_Fail; |
293 | | // Calling the auto-generated decoder function. |
294 | 47.5k | if (Sparc_getFeatureBits(Instr->csh->mode, Sparc_FeatureV9)) { |
295 | 42.2k | Result = decodeInstruction_4(DecoderTableSparcV932, Instr, Insn, |
296 | 42.2k | Address, NULL); |
297 | 42.2k | } else { |
298 | 5.30k | Result = decodeInstruction_4(DecoderTableSparcV832, Instr, Insn, |
299 | 5.30k | Address, NULL); |
300 | 5.30k | } |
301 | 47.5k | if (Result != MCDisassembler_Fail) { |
302 | 2.44k | *Size = 4; |
303 | 2.44k | return Result; |
304 | 2.44k | } |
305 | | |
306 | 45.1k | Result = decodeInstruction_4(DecoderTableSparc32, Instr, Insn, Address, |
307 | 45.1k | NULL); |
308 | | |
309 | 45.1k | if (Result != MCDisassembler_Fail) { |
310 | 44.7k | *Size = 4; |
311 | 44.7k | return Result; |
312 | 44.7k | } |
313 | | |
314 | 349 | return MCDisassembler_Fail; |
315 | 45.1k | } |
316 | | |
317 | | static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch, |
318 | | uint64_t Address, uint64_t Offset, |
319 | | uint64_t Width, MCInst *MI, |
320 | | const void *Decoder) |
321 | 4.51k | { |
322 | | // Capstone doesn't support symbols. |
323 | 4.51k | return false; |
324 | 4.51k | } |
325 | | |
326 | | static DecodeStatus DecodeCall(MCInst *MI, unsigned insn, uint64_t Address, |
327 | | const void *Decoder) |
328 | 4.51k | { |
329 | 4.51k | unsigned Offset = fieldFromInstruction_4(insn, 0, 30); |
330 | 4.51k | int64_t CallTarget = Address + (SignExtend64(Offset, 30) * 4); |
331 | 4.51k | if (!tryAddingSymbolicOperand(CallTarget, false, Address, 0, 30, MI, |
332 | 4.51k | Decoder)) |
333 | 4.51k | MCOperand_CreateImm0(MI, CallTarget); |
334 | 4.51k | return MCDisassembler_Success; |
335 | 4.51k | } |
336 | | |
337 | | static DecodeStatus DecodeSIMM13(MCInst *MI, unsigned insn, uint64_t Address, |
338 | | const void *Decoder) |
339 | 4.04k | { |
340 | 4.04k | CS_ASSERT(isUIntN(13, insn)); |
341 | 4.04k | MCOperand_CreateImm0(MI, (SignExtend64((insn), 13))); |
342 | 4.04k | return MCDisassembler_Success; |
343 | 4.04k | } |
344 | | |
345 | | DecodeStatus Sparc_LLVM_getInstruction(csh handle, const uint8_t *Bytes, |
346 | | size_t ByteLen, MCInst *MI, |
347 | | uint16_t *Size, uint64_t Address, |
348 | | void *Info) |
349 | 48.2k | { |
350 | 48.2k | uint64_t s = 0; |
351 | 48.2k | DecodeStatus status = |
352 | 48.2k | getInstruction(MI, &s, Bytes, ByteLen, Address, NULL); |
353 | 48.2k | *Size = (uint16_t)s; |
354 | 48.2k | return status; |
355 | 48.2k | } |