/src/capstonenext/arch/PowerPC/PPCDisassembler.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 | | //===------ PPCDisassembler.cpp - Disassembler for PowerPC ------*- 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 | | #include <capstone/platform.h> |
24 | | #include <stdio.h> |
25 | | #include <stdlib.h> |
26 | | #include <string.h> |
27 | | |
28 | | #include "../../LEB128.h" |
29 | | #include "../../MCDisassembler.h" |
30 | | #include "../../MCFixedLenDisassembler.h" |
31 | | #include "../../MCInst.h" |
32 | | #include "../../MCInstPrinter.h" |
33 | | #include "../../MCInstrDesc.h" |
34 | | #include "../../MCRegisterInfo.h" |
35 | | #include "../../SStream.h" |
36 | | #include "../../utils.h" |
37 | | #include "PPCLinkage.h" |
38 | | #include "PPCMapping.h" |
39 | | #include "PPCMCTargetDesc.h" |
40 | | #include "PPCPredicates.h" |
41 | | |
42 | | #define CONCAT(a, b) CONCAT_(a, b) |
43 | | #define CONCAT_(a, b) a##_##b |
44 | | |
45 | | DEFINE_PPC_REGCLASSES |
46 | | |
47 | | #define DEBUG_TYPE "ppc-disassembler" |
48 | | |
49 | | DecodeStatus getInstruction(csh ud, const uint8_t *Bytes, size_t BytesLen, |
50 | | MCInst *MI, uint16_t *Size, uint64_t Address, |
51 | | void *Info); |
52 | | // end anonymous namespace |
53 | | |
54 | | static DecodeStatus decodeCondBrTarget(MCInst *Inst, unsigned Imm, |
55 | | uint64_t Address, const void *Decoder) |
56 | 6.88k | { |
57 | 6.88k | MCOperand_CreateImm0(Inst, (SignExtend32((Imm), 14))); |
58 | 6.88k | return MCDisassembler_Success; |
59 | 6.88k | } |
60 | | |
61 | | static DecodeStatus decodeDirectBrTarget(MCInst *Inst, unsigned Imm, |
62 | | uint64_t Address, const void *Decoder) |
63 | 631 | { |
64 | 631 | int32_t Offset = SignExtend32((Imm), 24); |
65 | 631 | MCOperand_CreateImm0(Inst, (Offset)); |
66 | 631 | return MCDisassembler_Success; |
67 | 631 | } |
68 | | |
69 | | // FIXME: These can be generated by TableGen from the existing register |
70 | | // encoding values! |
71 | | |
72 | | static DecodeStatus decodeRegisterClass(MCInst *Inst, uint64_t RegNo, |
73 | | const MCPhysReg *Regs) |
74 | 74.2k | { |
75 | 74.2k | MCOperand_CreateReg0(Inst, (Regs[RegNo])); |
76 | 74.2k | return MCDisassembler_Success; |
77 | 74.2k | } |
78 | | |
79 | | static DecodeStatus DecodeCRRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
80 | | uint64_t Address, |
81 | | const void *Decoder) |
82 | 5.00k | { |
83 | 5.00k | return decodeRegisterClass(Inst, RegNo, CRRegs); |
84 | 5.00k | } |
85 | | |
86 | | static DecodeStatus DecodeCRBITRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
87 | | uint64_t Address, |
88 | | const void *Decoder) |
89 | 18.1k | { |
90 | 18.1k | return decodeRegisterClass(Inst, RegNo, CRBITRegs); |
91 | 18.1k | } |
92 | | |
93 | | static DecodeStatus DecodeF4RCRegisterClass(MCInst *Inst, uint64_t RegNo, |
94 | | uint64_t Address, |
95 | | const void *Decoder) |
96 | 5.73k | { |
97 | 5.73k | return decodeRegisterClass(Inst, RegNo, FRegs); |
98 | 5.73k | } |
99 | | |
100 | | static DecodeStatus DecodeF8RCRegisterClass(MCInst *Inst, uint64_t RegNo, |
101 | | uint64_t Address, |
102 | | const void *Decoder) |
103 | 13.1k | { |
104 | 13.1k | return decodeRegisterClass(Inst, RegNo, FRegs); |
105 | 13.1k | } |
106 | | |
107 | | static DecodeStatus DecodeFpRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
108 | | uint64_t Address, |
109 | | const void *Decoder) |
110 | 934 | { |
111 | 934 | if (RegNo > 30 || (RegNo & 1)) |
112 | 40 | return MCDisassembler_Fail; |
113 | 894 | return decodeRegisterClass(Inst, RegNo >> 1, FpRegs); |
114 | 934 | } |
115 | | |
116 | | static DecodeStatus DecodeVFRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
117 | | uint64_t Address, |
118 | | const void *Decoder) |
119 | 975 | { |
120 | 975 | return decodeRegisterClass(Inst, RegNo, VFRegs); |
121 | 975 | } |
122 | | |
123 | | static DecodeStatus DecodeVRRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
124 | | uint64_t Address, |
125 | | const void *Decoder) |
126 | 10.0k | { |
127 | 10.0k | return decodeRegisterClass(Inst, RegNo, VRegs); |
128 | 10.0k | } |
129 | | |
130 | | static DecodeStatus DecodeVSRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
131 | | uint64_t Address, |
132 | | const void *Decoder) |
133 | 14.8k | { |
134 | 14.8k | return decodeRegisterClass(Inst, RegNo, VSRegs); |
135 | 14.8k | } |
136 | | |
137 | | static DecodeStatus DecodeVSFRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
138 | | uint64_t Address, |
139 | | const void *Decoder) |
140 | 4.67k | { |
141 | 4.67k | return decodeRegisterClass(Inst, RegNo, VSFRegs); |
142 | 4.67k | } |
143 | | |
144 | | static DecodeStatus DecodeVSSRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
145 | | uint64_t Address, |
146 | | const void *Decoder) |
147 | 2.53k | { |
148 | 2.53k | return decodeRegisterClass(Inst, RegNo, VSSRegs); |
149 | 2.53k | } |
150 | | |
151 | | static DecodeStatus DecodeGPRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
152 | | uint64_t Address, |
153 | | const void *Decoder) |
154 | 72.5k | { |
155 | 72.5k | return decodeRegisterClass(Inst, RegNo, RRegs); |
156 | 72.5k | } |
157 | | |
158 | | static DecodeStatus DecodeGPRC_NOR0RegisterClass(MCInst *Inst, uint64_t RegNo, |
159 | | uint64_t Address, |
160 | | const void *Decoder) |
161 | 16.8k | { |
162 | 16.8k | return decodeRegisterClass(Inst, RegNo, RRegsNoR0); |
163 | 16.8k | } |
164 | | |
165 | | static DecodeStatus DecodeG8RCRegisterClass(MCInst *Inst, uint64_t RegNo, |
166 | | uint64_t Address, |
167 | | const void *Decoder) |
168 | 15.7k | { |
169 | 15.7k | return decodeRegisterClass(Inst, RegNo, XRegs); |
170 | 15.7k | } |
171 | | |
172 | | static DecodeStatus DecodeG8pRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
173 | | uint64_t Address, |
174 | | const void *Decoder) |
175 | 464 | { |
176 | 464 | return decodeRegisterClass(Inst, RegNo, XRegs); |
177 | 464 | } |
178 | | |
179 | | static DecodeStatus DecodeG8RC_NOX0RegisterClass(MCInst *Inst, uint64_t RegNo, |
180 | | uint64_t Address, |
181 | | const void *Decoder) |
182 | 296 | { |
183 | 296 | return decodeRegisterClass(Inst, RegNo, XRegsNoX0); |
184 | 296 | } |
185 | | |
186 | 1.75k | #define DecodePointerLikeRegClass0 DecodeGPRCRegisterClass |
187 | 11.4k | #define DecodePointerLikeRegClass1 DecodeGPRC_NOR0RegisterClass |
188 | | |
189 | | static DecodeStatus DecodeSPERCRegisterClass(MCInst *Inst, uint64_t RegNo, |
190 | | uint64_t Address, |
191 | | const void *Decoder) |
192 | 0 | { |
193 | 0 | return decodeRegisterClass(Inst, RegNo, SPERegs); |
194 | 0 | } |
195 | | |
196 | | static DecodeStatus DecodeACCRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
197 | | uint64_t Address, |
198 | | const void *Decoder) |
199 | 0 | { |
200 | 0 | return decodeRegisterClass(Inst, RegNo, ACCRegs); |
201 | 0 | } |
202 | | |
203 | | static DecodeStatus DecodeWACCRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
204 | | uint64_t Address, |
205 | | const void *Decoder) |
206 | 202 | { |
207 | 202 | return decodeRegisterClass(Inst, RegNo, WACCRegs); |
208 | 202 | } |
209 | | |
210 | | static DecodeStatus DecodeWACC_HIRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
211 | | uint64_t Address, |
212 | | const void *Decoder) |
213 | 49 | { |
214 | 49 | return decodeRegisterClass(Inst, RegNo, WACC_HIRegs); |
215 | 49 | } |
216 | | |
217 | | // TODO: Make this function static when the register class is used by a new |
218 | | // instruction. |
219 | | DecodeStatus DecodeDMRROWRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
220 | | uint64_t Address, const void *Decoder) |
221 | 0 | { |
222 | 0 | return decodeRegisterClass(Inst, RegNo, DMRROWRegs); |
223 | 0 | } |
224 | | |
225 | | static DecodeStatus DecodeDMRROWpRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
226 | | uint64_t Address, |
227 | | const void *Decoder) |
228 | 67 | { |
229 | 67 | return decodeRegisterClass(Inst, RegNo, DMRROWpRegs); |
230 | 67 | } |
231 | | |
232 | | static DecodeStatus DecodeDMRRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
233 | | uint64_t Address, |
234 | | const void *Decoder) |
235 | 32 | { |
236 | 32 | return decodeRegisterClass(Inst, RegNo, DMRRegs); |
237 | 32 | } |
238 | | |
239 | | // TODO: Make this function static when the register class is used by a new |
240 | | // instruction. |
241 | | DecodeStatus DecodeDMRpRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
242 | | uint64_t Address, const void *Decoder) |
243 | 0 | { |
244 | 0 | return decodeRegisterClass(Inst, RegNo, DMRpRegs); |
245 | 0 | } |
246 | | |
247 | | static DecodeStatus DecodeVSRpRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
248 | | uint64_t Address, |
249 | | const void *Decoder) |
250 | 644 | { |
251 | 644 | return decodeRegisterClass(Inst, RegNo, VSRpRegs); |
252 | 644 | } |
253 | | |
254 | 1.42k | #define DecodeQSRCRegisterClass DecodeQFRCRegisterClass |
255 | 281 | #define DecodeQBRCRegisterClass DecodeQFRCRegisterClass |
256 | | |
257 | | static DecodeStatus DecodeQFRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
258 | | uint64_t Address, |
259 | | const void *Decoder) |
260 | 13.0k | { |
261 | 13.0k | return decodeRegisterClass(Inst, RegNo, QFRegs); |
262 | 13.0k | } |
263 | | |
264 | | #define DEFINE_decodeUImmOperand(N) \ |
265 | | static DecodeStatus CONCAT(decodeUImmOperand, \ |
266 | | N)(MCInst * Inst, uint64_t Imm, \ |
267 | | int64_t Address, const void *Decoder) \ |
268 | 19.8k | { \ |
269 | 19.8k | if (!isUIntN(N, Imm)) \ |
270 | 19.8k | return MCDisassembler_Fail; \ |
271 | 19.8k | MCOperand_CreateImm0(Inst, (Imm)); \ |
272 | 19.8k | return MCDisassembler_Success; \ |
273 | 19.8k | } PPCDisassembler.c:decodeUImmOperand_5 Line | Count | Source | 268 | 11.9k | { \ | 269 | 11.9k | if (!isUIntN(N, Imm)) \ | 270 | 11.9k | return MCDisassembler_Fail; \ | 271 | 11.9k | MCOperand_CreateImm0(Inst, (Imm)); \ | 272 | 11.9k | return MCDisassembler_Success; \ | 273 | 11.9k | } |
PPCDisassembler.c:decodeUImmOperand_1 Line | Count | Source | 268 | 1.20k | { \ | 269 | 1.20k | if (!isUIntN(N, Imm)) \ | 270 | 1.20k | return MCDisassembler_Fail; \ | 271 | 1.20k | MCOperand_CreateImm0(Inst, (Imm)); \ | 272 | 1.20k | return MCDisassembler_Success; \ | 273 | 1.20k | } |
PPCDisassembler.c:decodeUImmOperand_4 Line | Count | Source | 268 | 477 | { \ | 269 | 477 | if (!isUIntN(N, Imm)) \ | 270 | 477 | return MCDisassembler_Fail; \ | 271 | 477 | MCOperand_CreateImm0(Inst, (Imm)); \ | 272 | 469 | return MCDisassembler_Success; \ | 273 | 477 | } |
PPCDisassembler.c:decodeUImmOperand_3 Line | Count | Source | 268 | 1.29k | { \ | 269 | 1.29k | if (!isUIntN(N, Imm)) \ | 270 | 1.29k | return MCDisassembler_Fail; \ | 271 | 1.29k | MCOperand_CreateImm0(Inst, (Imm)); \ | 272 | 1.29k | return MCDisassembler_Success; \ | 273 | 1.29k | } |
PPCDisassembler.c:decodeUImmOperand_16 Line | Count | Source | 268 | 2.12k | { \ | 269 | 2.12k | if (!isUIntN(N, Imm)) \ | 270 | 2.12k | return MCDisassembler_Fail; \ | 271 | 2.12k | MCOperand_CreateImm0(Inst, (Imm)); \ | 272 | 2.12k | return MCDisassembler_Success; \ | 273 | 2.12k | } |
PPCDisassembler.c:decodeUImmOperand_6 Line | Count | Source | 268 | 1.33k | { \ | 269 | 1.33k | if (!isUIntN(N, Imm)) \ | 270 | 1.33k | return MCDisassembler_Fail; \ | 271 | 1.33k | MCOperand_CreateImm0(Inst, (Imm)); \ | 272 | 1.33k | return MCDisassembler_Success; \ | 273 | 1.33k | } |
PPCDisassembler.c:decodeUImmOperand_2 Line | Count | Source | 268 | 1.13k | { \ | 269 | 1.13k | if (!isUIntN(N, Imm)) \ | 270 | 1.13k | return MCDisassembler_Fail; \ | 271 | 1.13k | MCOperand_CreateImm0(Inst, (Imm)); \ | 272 | 1.13k | return MCDisassembler_Success; \ | 273 | 1.13k | } |
PPCDisassembler.c:decodeUImmOperand_10 Line | Count | Source | 268 | 80 | { \ | 269 | 80 | if (!isUIntN(N, Imm)) \ | 270 | 80 | return MCDisassembler_Fail; \ | 271 | 80 | MCOperand_CreateImm0(Inst, (Imm)); \ | 272 | 80 | return MCDisassembler_Success; \ | 273 | 80 | } |
PPCDisassembler.c:decodeUImmOperand_8 Line | Count | Source | 268 | 62 | { \ | 269 | 62 | if (!isUIntN(N, Imm)) \ | 270 | 62 | return MCDisassembler_Fail; \ | 271 | 62 | MCOperand_CreateImm0(Inst, (Imm)); \ | 272 | 62 | return MCDisassembler_Success; \ | 273 | 62 | } |
PPCDisassembler.c:decodeUImmOperand_7 Line | Count | Source | 268 | 86 | { \ | 269 | 86 | if (!isUIntN(N, Imm)) \ | 270 | 86 | return MCDisassembler_Fail; \ | 271 | 86 | MCOperand_CreateImm0(Inst, (Imm)); \ | 272 | 86 | return MCDisassembler_Success; \ | 273 | 86 | } |
PPCDisassembler.c:decodeUImmOperand_12 Line | Count | Source | 268 | 101 | { \ | 269 | 101 | if (!isUIntN(N, Imm)) \ | 270 | 101 | return MCDisassembler_Fail; \ | 271 | 101 | MCOperand_CreateImm0(Inst, (Imm)); \ | 272 | 101 | return MCDisassembler_Success; \ | 273 | 101 | } |
|
274 | | DEFINE_decodeUImmOperand(1); |
275 | | DEFINE_decodeUImmOperand(2); |
276 | | DEFINE_decodeUImmOperand(3); |
277 | | DEFINE_decodeUImmOperand(4); |
278 | | DEFINE_decodeUImmOperand(5); |
279 | | DEFINE_decodeUImmOperand(6); |
280 | | DEFINE_decodeUImmOperand(7); |
281 | | DEFINE_decodeUImmOperand(8); |
282 | | DEFINE_decodeUImmOperand(10); |
283 | | DEFINE_decodeUImmOperand(12); |
284 | | DEFINE_decodeUImmOperand(16); |
285 | | |
286 | | #define DEFINE_decodeSImmOperand(N) \ |
287 | | static DecodeStatus CONCAT(decodeSImmOperand, \ |
288 | | N)(MCInst * Inst, uint64_t Imm, \ |
289 | | int64_t Address, const void *Decoder) \ |
290 | 3.87k | { \ |
291 | 3.87k | if (!isUIntN(N, Imm)) \ |
292 | 3.87k | return MCDisassembler_Fail; \ |
293 | 3.87k | MCOperand_CreateImm0(Inst, (SignExtend64((Imm), N))); \ |
294 | 3.87k | return MCDisassembler_Success; \ |
295 | 3.87k | } PPCDisassembler.c:decodeSImmOperand_16 Line | Count | Source | 290 | 3.32k | { \ | 291 | 3.32k | if (!isUIntN(N, Imm)) \ | 292 | 3.32k | return MCDisassembler_Fail; \ | 293 | 3.32k | MCOperand_CreateImm0(Inst, (SignExtend64((Imm), N))); \ | 294 | 3.32k | return MCDisassembler_Success; \ | 295 | 3.32k | } |
PPCDisassembler.c:decodeSImmOperand_5 Line | Count | Source | 290 | 121 | { \ | 291 | 121 | if (!isUIntN(N, Imm)) \ | 292 | 121 | return MCDisassembler_Fail; \ | 293 | 121 | MCOperand_CreateImm0(Inst, (SignExtend64((Imm), N))); \ | 294 | 121 | return MCDisassembler_Success; \ | 295 | 121 | } |
PPCDisassembler.c:decodeSImmOperand_34 Line | Count | Source | 290 | 428 | { \ | 291 | 428 | if (!isUIntN(N, Imm)) \ | 292 | 428 | return MCDisassembler_Fail; \ | 293 | 428 | MCOperand_CreateImm0(Inst, (SignExtend64((Imm), N))); \ | 294 | 428 | return MCDisassembler_Success; \ | 295 | 428 | } |
|
296 | | DEFINE_decodeSImmOperand(16); |
297 | | DEFINE_decodeSImmOperand(5); |
298 | | DEFINE_decodeSImmOperand(34); |
299 | | |
300 | | static DecodeStatus decodeImmZeroOperand(MCInst *Inst, uint64_t Imm, |
301 | | int64_t Address, const void *Decoder) |
302 | 290 | { |
303 | 290 | if (Imm != 0) |
304 | 4 | return MCDisassembler_Fail; |
305 | 286 | MCOperand_CreateImm0(Inst, (Imm)); |
306 | 286 | return MCDisassembler_Success; |
307 | 290 | } |
308 | | |
309 | | static DecodeStatus decodeVSRpEvenOperands(MCInst *Inst, uint64_t RegNo, |
310 | | uint64_t Address, |
311 | | const void *Decoder) |
312 | 0 | { |
313 | 0 | if (RegNo & 1) |
314 | 0 | return MCDisassembler_Fail; |
315 | 0 | MCOperand_CreateReg0(Inst, (VSRpRegs[RegNo >> 1])); |
316 | 0 | return MCDisassembler_Success; |
317 | 0 | } |
318 | | |
319 | | static DecodeStatus decodeDispSPE8Operand(MCInst *Inst, uint64_t Imm, |
320 | | int64_t Address, const void *Decoder) |
321 | 0 | { |
322 | | // Decode the dispSPE8 field, which has 5-bits, 8-byte aligned. |
323 | |
|
324 | 0 | uint64_t Disp = Imm & 0x1F; |
325 | |
|
326 | 0 | MCOperand_CreateImm0(Inst, (Disp << 3)); |
327 | 0 | return MCDisassembler_Success; |
328 | 0 | } |
329 | | |
330 | | static DecodeStatus decodeDispSPE4Operand(MCInst *Inst, uint64_t Imm, |
331 | | int64_t Address, const void *Decoder) |
332 | 0 | { |
333 | | // Decode the dispSPE8 field, which has 5-bits, 4-byte aligned. |
334 | |
|
335 | 0 | uint64_t Disp = Imm & 0x1F; |
336 | |
|
337 | 0 | MCOperand_CreateImm0(Inst, (Disp << 2)); |
338 | 0 | return MCDisassembler_Success; |
339 | 0 | } |
340 | | |
341 | | static DecodeStatus decodeDispSPE2Operand(MCInst *Inst, uint64_t Imm, |
342 | | int64_t Address, const void *Decoder) |
343 | 0 | { |
344 | | // Decode the dispSPE8 field, which has 5-bits, 2-byte aligned. |
345 | |
|
346 | 0 | uint64_t Disp = Imm & 0x1F; |
347 | 0 | MCOperand_CreateImm0(Inst, (Disp << 1)); |
348 | 0 | return MCDisassembler_Success; |
349 | 0 | } |
350 | | |
351 | | static DecodeStatus decodeDispRIXOperand(MCInst *Inst, uint64_t Imm, |
352 | | int64_t Address, const void *Decoder) |
353 | 1.27k | { |
354 | | // The rix displacement is an immediate shifted by 2 |
355 | 1.27k | MCOperand_CreateImm0(Inst, (SignExtend64((Imm << 2), 16))); |
356 | 1.27k | return MCDisassembler_Success; |
357 | 1.27k | } |
358 | | |
359 | | static DecodeStatus decodeDispRIX16Operand(MCInst *Inst, uint64_t Imm, |
360 | | int64_t Address, const void *Decoder) |
361 | 246 | { |
362 | | // The rix16 displacement has 12-bits which are shifted by 4. |
363 | 246 | MCOperand_CreateImm0(Inst, (SignExtend64((Imm << 4), 16))); |
364 | 246 | return MCDisassembler_Success; |
365 | 246 | } |
366 | | |
367 | | static DecodeStatus decodeDispRIHashOperand(MCInst *Inst, uint64_t Imm, |
368 | | int64_t Address, |
369 | | const void *Decoder) |
370 | 20 | { |
371 | | // Decode the disp field for a hash store or hash check operation. |
372 | | // The field is composed of an immediate value that is 6 bits |
373 | | // and covers the range -8 to -512. The immediate is always negative and 2s |
374 | | // complement which is why we sign extend a 7 bit value. |
375 | 20 | const int64_t Disp = SignExtend64(((Imm & 0x3F) + 64), 7) * 8; |
376 | | |
377 | 20 | MCOperand_CreateImm0(Inst, (Disp)); |
378 | 20 | return MCDisassembler_Success; |
379 | 20 | } |
380 | | |
381 | | static DecodeStatus decodeCRBitMOperand(MCInst *Inst, uint64_t Imm, |
382 | | int64_t Address, const void *Decoder) |
383 | 584 | { |
384 | | // The cr bit encoding is 0x80 >> cr_reg_num. |
385 | | |
386 | 584 | unsigned Zeros = CountTrailingZeros_32(Imm); |
387 | 584 | if (Zeros >= 8) |
388 | 3 | return MCDisassembler_Fail; |
389 | | |
390 | 581 | MCOperand_CreateReg0(Inst, (CRRegs[7 - Zeros])); |
391 | 581 | return MCDisassembler_Success; |
392 | 584 | } |
393 | | |
394 | | #include "PPCGenDisassemblerTables.inc" |
395 | | |
396 | | DecodeStatus getInstruction(csh ud, const uint8_t *Bytes, size_t BytesLen, |
397 | | MCInst *MI, uint16_t *Size, uint64_t Address, |
398 | | void *Info) |
399 | 37.2k | { |
400 | | // If this is an 8-byte prefixed instruction, handle it here. |
401 | | // Note: prefixed instructions aren't technically 8-byte entities - the |
402 | | // prefix |
403 | | // appears in memory at an address 4 bytes prior to that of the base |
404 | | // instruction regardless of endianness. So we read the two pieces and |
405 | | // rebuild the 8-byte instruction. |
406 | | // TODO: In this function we call decodeInstruction several times with |
407 | | // different decoder tables. It may be possible to only call once by |
408 | | // looking at the top 6 bits of the instruction. |
409 | 37.2k | if (PPC_getFeatureBits(MI->csh->mode, PPC_FeaturePrefixInstrs) && |
410 | 37.2k | BytesLen >= 8) { |
411 | 35.5k | uint32_t Prefix = readBytes32(MI, Bytes); |
412 | 35.5k | uint32_t BaseInst = readBytes32(MI, Bytes + 4); |
413 | 35.5k | uint64_t Inst = BaseInst | (uint64_t)Prefix << 32; |
414 | 35.5k | DecodeStatus result = decodeInstruction_4(DecoderTable64, MI, |
415 | 35.5k | Inst, Address, NULL); |
416 | 35.5k | if (result != MCDisassembler_Fail) { |
417 | 465 | *Size = 8; |
418 | 465 | return result; |
419 | 465 | } |
420 | 35.5k | } |
421 | | |
422 | | // Get the four bytes of the instruction. |
423 | 36.7k | *Size = 4; |
424 | 36.7k | if (BytesLen < 4) { |
425 | 503 | *Size = 0; |
426 | 503 | return MCDisassembler_Fail; |
427 | 503 | } |
428 | | |
429 | | // Read the instruction in the proper endianness. |
430 | 36.2k | uint64_t Inst = readBytes32(MI, Bytes); |
431 | | |
432 | 36.2k | if (PPC_getFeatureBits(MI->csh->mode, PPC_FeatureQPX)) { |
433 | 15.7k | DecodeStatus result = decodeInstruction_4(DecoderTableQPX32, MI, |
434 | 15.7k | Inst, Address, NULL); |
435 | 15.7k | if (result != MCDisassembler_Fail) |
436 | 1.28k | return result; |
437 | 20.5k | } else if (PPC_getFeatureBits(MI->csh->mode, PPC_FeatureSPE)) { |
438 | 0 | DecodeStatus result = decodeInstruction_4(DecoderTableSPE32, MI, |
439 | 0 | Inst, Address, NULL); |
440 | 0 | if (result != MCDisassembler_Fail) |
441 | 0 | return result; |
442 | 20.5k | } else if (PPC_getFeatureBits(MI->csh->mode, PPC_FeaturePS)) { |
443 | 8.03k | DecodeStatus result = decodeInstruction_4(DecoderTablePS32, MI, |
444 | 8.03k | Inst, Address, NULL); |
445 | 8.03k | if (result != MCDisassembler_Fail) |
446 | 669 | return result; |
447 | 8.03k | } |
448 | | |
449 | 34.3k | return decodeInstruction_4(DecoderTable32, MI, Inst, Address, NULL); |
450 | 36.2k | } |
451 | | |
452 | | DecodeStatus PPC_LLVM_getInstruction(csh handle, const uint8_t *Bytes, |
453 | | size_t BytesLen, MCInst *MI, |
454 | | uint16_t *Size, uint64_t Address, |
455 | | void *Info) |
456 | 37.2k | { |
457 | 37.2k | return getInstruction(handle, Bytes, BytesLen, MI, Size, Address, Info); |
458 | 37.2k | } |