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