/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 | 5.50k | { |
57 | 5.50k | MCOperand_CreateImm0(Inst, (SignExtend32((Imm), 14))); |
58 | 5.50k | return MCDisassembler_Success; |
59 | 5.50k | } |
60 | | |
61 | | static DecodeStatus decodeDirectBrTarget(MCInst *Inst, unsigned Imm, |
62 | | uint64_t Address, const void *Decoder) |
63 | 880 | { |
64 | 880 | int32_t Offset = SignExtend32((Imm), 24); |
65 | 880 | MCOperand_CreateImm0(Inst, (Offset)); |
66 | 880 | return MCDisassembler_Success; |
67 | 880 | } |
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 | 129k | { |
75 | 129k | MCOperand_CreateReg0(Inst, (Regs[RegNo])); |
76 | 129k | return MCDisassembler_Success; |
77 | 129k | } |
78 | | |
79 | | static DecodeStatus DecodeCRRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
80 | | uint64_t Address, |
81 | | const void *Decoder) |
82 | 6.14k | { |
83 | 6.14k | return decodeRegisterClass(Inst, RegNo, CRRegs); |
84 | 6.14k | } |
85 | | |
86 | | static DecodeStatus DecodeCRBITRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
87 | | uint64_t Address, |
88 | | const void *Decoder) |
89 | 15.4k | { |
90 | 15.4k | return decodeRegisterClass(Inst, RegNo, CRBITRegs); |
91 | 15.4k | } |
92 | | |
93 | | static DecodeStatus DecodeF4RCRegisterClass(MCInst *Inst, uint64_t RegNo, |
94 | | uint64_t Address, |
95 | | const void *Decoder) |
96 | 6.53k | { |
97 | 6.53k | return decodeRegisterClass(Inst, RegNo, FRegs); |
98 | 6.53k | } |
99 | | |
100 | | static DecodeStatus DecodeF8RCRegisterClass(MCInst *Inst, uint64_t RegNo, |
101 | | uint64_t Address, |
102 | | const void *Decoder) |
103 | 16.9k | { |
104 | 16.9k | return decodeRegisterClass(Inst, RegNo, FRegs); |
105 | 16.9k | } |
106 | | |
107 | | static DecodeStatus DecodeVFRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
108 | | uint64_t Address, |
109 | | const void *Decoder) |
110 | 1.01k | { |
111 | 1.01k | return decodeRegisterClass(Inst, RegNo, VFRegs); |
112 | 1.01k | } |
113 | | |
114 | | static DecodeStatus DecodeVRRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
115 | | uint64_t Address, |
116 | | const void *Decoder) |
117 | 14.8k | { |
118 | 14.8k | return decodeRegisterClass(Inst, RegNo, VRegs); |
119 | 14.8k | } |
120 | | |
121 | | static DecodeStatus DecodeVSRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
122 | | uint64_t Address, |
123 | | const void *Decoder) |
124 | 16.2k | { |
125 | 16.2k | return decodeRegisterClass(Inst, RegNo, VSRegs); |
126 | 16.2k | } |
127 | | |
128 | | static DecodeStatus DecodeVSFRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
129 | | uint64_t Address, |
130 | | const void *Decoder) |
131 | 2.65k | { |
132 | 2.65k | return decodeRegisterClass(Inst, RegNo, VSFRegs); |
133 | 2.65k | } |
134 | | |
135 | | static DecodeStatus DecodeVSSRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
136 | | uint64_t Address, |
137 | | const void *Decoder) |
138 | 2.62k | { |
139 | 2.62k | return decodeRegisterClass(Inst, RegNo, VSSRegs); |
140 | 2.62k | } |
141 | | |
142 | | static DecodeStatus DecodeGPRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
143 | | uint64_t Address, |
144 | | const void *Decoder) |
145 | 115k | { |
146 | 115k | return decodeRegisterClass(Inst, RegNo, RRegs); |
147 | 115k | } |
148 | | |
149 | | static DecodeStatus DecodeGPRC_NOR0RegisterClass(MCInst *Inst, uint64_t RegNo, |
150 | | uint64_t Address, |
151 | | const void *Decoder) |
152 | 10.1k | { |
153 | 10.1k | return decodeRegisterClass(Inst, RegNo, RRegsNoR0); |
154 | 10.1k | } |
155 | | |
156 | | static DecodeStatus DecodeG8RCRegisterClass(MCInst *Inst, uint64_t RegNo, |
157 | | uint64_t Address, |
158 | | const void *Decoder) |
159 | 28.5k | { |
160 | 28.5k | return decodeRegisterClass(Inst, RegNo, XRegs); |
161 | 28.5k | } |
162 | | |
163 | | static DecodeStatus DecodeG8pRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
164 | | uint64_t Address, |
165 | | const void *Decoder) |
166 | 621 | { |
167 | 621 | return decodeRegisterClass(Inst, RegNo, XRegs); |
168 | 621 | } |
169 | | |
170 | | static DecodeStatus DecodeG8RC_NOX0RegisterClass(MCInst *Inst, uint64_t RegNo, |
171 | | uint64_t Address, |
172 | | const void *Decoder) |
173 | 60 | { |
174 | 60 | return decodeRegisterClass(Inst, RegNo, XRegsNoX0); |
175 | 60 | } |
176 | | |
177 | 2.80k | #define DecodePointerLikeRegClass0 DecodeGPRCRegisterClass |
178 | 4.42k | #define DecodePointerLikeRegClass1 DecodeGPRC_NOR0RegisterClass |
179 | | |
180 | | static DecodeStatus DecodeSPERCRegisterClass(MCInst *Inst, uint64_t RegNo, |
181 | | uint64_t Address, |
182 | | const void *Decoder) |
183 | 0 | { |
184 | 0 | return decodeRegisterClass(Inst, RegNo, SPERegs); |
185 | 0 | } |
186 | | |
187 | | static DecodeStatus DecodeACCRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
188 | | uint64_t Address, |
189 | | const void *Decoder) |
190 | 0 | { |
191 | 0 | return decodeRegisterClass(Inst, RegNo, ACCRegs); |
192 | 0 | } |
193 | | |
194 | | static DecodeStatus DecodeWACCRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
195 | | uint64_t Address, |
196 | | const void *Decoder) |
197 | 74 | { |
198 | 74 | return decodeRegisterClass(Inst, RegNo, WACCRegs); |
199 | 74 | } |
200 | | |
201 | | static DecodeStatus DecodeWACC_HIRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
202 | | uint64_t Address, |
203 | | const void *Decoder) |
204 | 146 | { |
205 | 146 | return decodeRegisterClass(Inst, RegNo, WACC_HIRegs); |
206 | 146 | } |
207 | | |
208 | | // TODO: Make this function static when the register class is used by a new |
209 | | // instruction. |
210 | | DecodeStatus DecodeDMRROWRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
211 | | uint64_t Address, const void *Decoder) |
212 | 0 | { |
213 | 0 | return decodeRegisterClass(Inst, RegNo, DMRROWRegs); |
214 | 0 | } |
215 | | |
216 | | static DecodeStatus DecodeDMRROWpRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
217 | | uint64_t Address, |
218 | | const void *Decoder) |
219 | 50 | { |
220 | 50 | return decodeRegisterClass(Inst, RegNo, DMRROWpRegs); |
221 | 50 | } |
222 | | |
223 | | static DecodeStatus DecodeDMRRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
224 | | uint64_t Address, |
225 | | const void *Decoder) |
226 | 64 | { |
227 | 64 | return decodeRegisterClass(Inst, RegNo, DMRRegs); |
228 | 64 | } |
229 | | |
230 | | // TODO: Make this function static when the register class is used by a new |
231 | | // instruction. |
232 | | DecodeStatus DecodeDMRpRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
233 | | uint64_t Address, const void *Decoder) |
234 | 0 | { |
235 | 0 | return decodeRegisterClass(Inst, RegNo, DMRpRegs); |
236 | 0 | } |
237 | | |
238 | | static DecodeStatus DecodeVSRpRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
239 | | uint64_t Address, |
240 | | const void *Decoder) |
241 | 707 | { |
242 | 707 | return decodeRegisterClass(Inst, RegNo, VSRpRegs); |
243 | 707 | } |
244 | | |
245 | 2.03k | #define DecodeQSRCRegisterClass DecodeQFRCRegisterClass |
246 | 1.25k | #define DecodeQBRCRegisterClass DecodeQFRCRegisterClass |
247 | | |
248 | | static DecodeStatus DecodeQFRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
249 | | uint64_t Address, |
250 | | const void *Decoder) |
251 | 23.1k | { |
252 | 23.1k | return decodeRegisterClass(Inst, RegNo, QFRegs); |
253 | 23.1k | } |
254 | | |
255 | | #define DEFINE_decodeUImmOperand(N) \ |
256 | | static DecodeStatus CONCAT(decodeUImmOperand, \ |
257 | | N)(MCInst * Inst, uint64_t Imm, \ |
258 | | int64_t Address, const void *Decoder) \ |
259 | 30.3k | { \ |
260 | 30.3k | MCOperand_CreateImm0(Inst, (Imm)); \ |
261 | 30.3k | return MCDisassembler_Success; \ |
262 | 30.3k | } PPCDisassembler.c:decodeUImmOperand_5 Line | Count | Source | 259 | 22.8k | { \ | 260 | 22.8k | MCOperand_CreateImm0(Inst, (Imm)); \ | 261 | 22.8k | return MCDisassembler_Success; \ | 262 | 22.8k | } |
PPCDisassembler.c:decodeUImmOperand_16 Line | Count | Source | 259 | 5.17k | { \ | 260 | 5.17k | MCOperand_CreateImm0(Inst, (Imm)); \ | 261 | 5.17k | return MCDisassembler_Success; \ | 262 | 5.17k | } |
PPCDisassembler.c:decodeUImmOperand_6 Line | Count | Source | 259 | 1.77k | { \ | 260 | 1.77k | MCOperand_CreateImm0(Inst, (Imm)); \ | 261 | 1.77k | return MCDisassembler_Success; \ | 262 | 1.77k | } |
PPCDisassembler.c:decodeUImmOperand_10 Line | Count | Source | 259 | 19 | { \ | 260 | 19 | MCOperand_CreateImm0(Inst, (Imm)); \ | 261 | 19 | return MCDisassembler_Success; \ | 262 | 19 | } |
PPCDisassembler.c:decodeUImmOperand_8 Line | Count | Source | 259 | 69 | { \ | 260 | 69 | MCOperand_CreateImm0(Inst, (Imm)); \ | 261 | 69 | return MCDisassembler_Success; \ | 262 | 69 | } |
PPCDisassembler.c:decodeUImmOperand_7 Line | Count | Source | 259 | 100 | { \ | 260 | 100 | MCOperand_CreateImm0(Inst, (Imm)); \ | 261 | 100 | return MCDisassembler_Success; \ | 262 | 100 | } |
PPCDisassembler.c:decodeUImmOperand_12 Line | Count | Source | 259 | 314 | { \ | 260 | 314 | MCOperand_CreateImm0(Inst, (Imm)); \ | 261 | 314 | return MCDisassembler_Success; \ | 262 | 314 | } |
|
263 | | DEFINE_decodeUImmOperand(5) DEFINE_decodeUImmOperand(16) |
264 | | DEFINE_decodeUImmOperand(6) DEFINE_decodeUImmOperand(10) |
265 | | DEFINE_decodeUImmOperand(8) DEFINE_decodeUImmOperand(7) |
266 | | DEFINE_decodeUImmOperand(12) |
267 | | |
268 | | #define DEFINE_decodeSImmOperand(N) \ |
269 | | static DecodeStatus CONCAT(decodeSImmOperand, \ |
270 | | N)(MCInst * Inst, uint64_t Imm, \ |
271 | | int64_t Address, const void *Decoder) \ |
272 | 9.50k | { \ |
273 | 9.50k | MCOperand_CreateImm0(Inst, (SignExtend64(Imm, N))); \ |
274 | 9.50k | return MCDisassembler_Success; \ |
275 | 9.50k | } PPCDisassembler.c:decodeSImmOperand_16 Line | Count | Source | 272 | 9.27k | { \ | 273 | 9.27k | MCOperand_CreateImm0(Inst, (SignExtend64(Imm, N))); \ | 274 | 9.27k | return MCDisassembler_Success; \ | 275 | 9.27k | } |
PPCDisassembler.c:decodeSImmOperand_5 Line | Count | Source | 272 | 28 | { \ | 273 | 28 | MCOperand_CreateImm0(Inst, (SignExtend64(Imm, N))); \ | 274 | 28 | return MCDisassembler_Success; \ | 275 | 28 | } |
PPCDisassembler.c:decodeSImmOperand_34 Line | Count | Source | 272 | 211 | { \ | 273 | 211 | MCOperand_CreateImm0(Inst, (SignExtend64(Imm, N))); \ | 274 | 211 | return MCDisassembler_Success; \ | 275 | 211 | } |
|
276 | | DEFINE_decodeSImmOperand(16) |
277 | | DEFINE_decodeSImmOperand(5) |
278 | | DEFINE_decodeSImmOperand(34) |
279 | | |
280 | | static DecodeStatus |
281 | | decodeImmZeroOperand(MCInst *Inst, uint64_t Imm, int64_t Address, |
282 | | const void *Decoder) |
283 | 365 | { |
284 | 365 | if (Imm != 0) |
285 | 24 | return MCDisassembler_Fail; |
286 | 341 | MCOperand_CreateImm0(Inst, (Imm)); |
287 | 341 | return MCDisassembler_Success; |
288 | 365 | } |
289 | | |
290 | | static DecodeStatus decodeVSRpEvenOperands(MCInst *Inst, uint64_t RegNo, |
291 | | uint64_t Address, |
292 | | const void *Decoder) |
293 | 0 | { |
294 | 0 | if (RegNo & 1) |
295 | 0 | return MCDisassembler_Fail; |
296 | 0 | MCOperand_CreateReg0(Inst, (VSRpRegs[RegNo >> 1])); |
297 | 0 | return MCDisassembler_Success; |
298 | 0 | } |
299 | | |
300 | | static DecodeStatus decodeMemRIOperands(MCInst *Inst, uint64_t Imm, |
301 | | int64_t Address, const void *Decoder) |
302 | 13.7k | { |
303 | | // Decode the memri field (imm, reg), which has the low 16-bits as the |
304 | | // displacement and the next 5 bits as the register #. |
305 | | |
306 | 13.7k | uint64_t Base = Imm >> 16; |
307 | 13.7k | uint64_t Disp = Imm & 0xFFFF; |
308 | | |
309 | 13.7k | switch (MCInst_getOpcode(Inst)) { |
310 | 6.15k | default: |
311 | 6.15k | break; |
312 | 6.15k | case PPC_LBZU: |
313 | 1.34k | case PPC_LHAU: |
314 | 2.10k | case PPC_LHZU: |
315 | 3.64k | case PPC_LWZU: |
316 | 4.07k | case PPC_LFSU: |
317 | 4.89k | case PPC_LFDU: |
318 | | // Add the tied output operand. |
319 | 4.89k | MCOperand_CreateReg0(Inst, (RRegsNoR0[Base])); |
320 | 4.89k | break; |
321 | 461 | case PPC_STBU: |
322 | 956 | case PPC_STHU: |
323 | 1.34k | case PPC_STWU: |
324 | 1.74k | case PPC_STFSU: |
325 | 2.71k | case PPC_STFDU: |
326 | 2.71k | MCInst_insert0(Inst, 0, |
327 | 2.71k | MCOperand_CreateReg1(Inst, RRegsNoR0[Base])); |
328 | 2.71k | break; |
329 | 13.7k | } |
330 | | |
331 | 13.7k | MCOperand_CreateImm0(Inst, (SignExtend64(Disp, 16))); |
332 | 13.7k | MCOperand_CreateReg0(Inst, (RRegsNoR0[Base])); |
333 | 13.7k | return MCDisassembler_Success; |
334 | 13.7k | } |
335 | | |
336 | | static DecodeStatus decodeMemRIXOperands(MCInst *Inst, uint64_t Imm, |
337 | | int64_t Address, const void *Decoder) |
338 | 2.09k | { |
339 | | // Decode the memrix field (imm, reg), which has the low 14-bits as the |
340 | | // displacement and the next 5 bits as the register #. |
341 | | |
342 | 2.09k | uint64_t Base = Imm >> 14; |
343 | 2.09k | uint64_t Disp = Imm & 0x3FFF; |
344 | | |
345 | 2.09k | if (MCInst_getOpcode(Inst) == PPC_LDU) |
346 | | // Add the tied output operand. |
347 | 576 | MCOperand_CreateReg0(Inst, (RRegsNoR0[Base])); |
348 | 1.52k | else if (MCInst_getOpcode(Inst) == PPC_STDU) |
349 | 440 | MCInst_insert0(Inst, 0, |
350 | 440 | MCOperand_CreateReg1(Inst, RRegsNoR0[Base])); |
351 | | |
352 | 2.09k | MCOperand_CreateImm0(Inst, (SignExtend64(Disp << 2, 16))); |
353 | 2.09k | MCOperand_CreateReg0(Inst, (RRegsNoR0[Base])); |
354 | 2.09k | return MCDisassembler_Success; |
355 | 2.09k | } |
356 | | |
357 | | static DecodeStatus decodeMemRIHashOperands(MCInst *Inst, uint64_t Imm, |
358 | | int64_t Address, |
359 | | const void *Decoder) |
360 | 21 | { |
361 | | // Decode the memrix field for a hash store or hash check operation. |
362 | | // The field is composed of a register and an immediate value that is 6 bits |
363 | | // and covers the range -8 to -512. The immediate is always negative and 2s |
364 | | // complement which is why we sign extend a 7 bit value. |
365 | 21 | const uint64_t Base = Imm >> 6; |
366 | 21 | const int64_t Disp = SignExtend64((Imm & 0x3F) + 64, 7) * 8; |
367 | | |
368 | 21 | MCOperand_CreateImm0(Inst, (Disp)); |
369 | 21 | MCOperand_CreateReg0(Inst, (RRegs[Base])); |
370 | 21 | return MCDisassembler_Success; |
371 | 21 | } |
372 | | |
373 | | static DecodeStatus decodeMemRIX16Operands(MCInst *Inst, uint64_t Imm, |
374 | | int64_t Address, const void *Decoder) |
375 | 492 | { |
376 | | // Decode the memrix16 field (imm, reg), which has the low 12-bits as the |
377 | | // displacement with 16-byte aligned, and the next 5 bits as the register #. |
378 | | |
379 | 492 | uint64_t Base = Imm >> 12; |
380 | 492 | uint64_t Disp = Imm & 0xFFF; |
381 | | |
382 | 492 | MCOperand_CreateImm0(Inst, (SignExtend64(Disp << 4, 16))); |
383 | 492 | MCOperand_CreateReg0(Inst, (RRegsNoR0[Base])); |
384 | 492 | return MCDisassembler_Success; |
385 | 492 | } |
386 | | |
387 | | static DecodeStatus decodeMemRI34PCRelOperands(MCInst *Inst, uint64_t Imm, |
388 | | int64_t Address, |
389 | | const void *Decoder) |
390 | 269 | { |
391 | | // Decode the memri34_pcrel field (imm, reg), which has the low 34-bits as |
392 | | // the displacement, and the next 5 bits as an immediate 0. |
393 | 269 | uint64_t Base = Imm >> 34; |
394 | 269 | uint64_t Disp = Imm & 0x3FFFFFFFFUL; |
395 | | |
396 | 269 | MCOperand_CreateImm0(Inst, (SignExtend64(Disp, 34))); |
397 | 269 | return decodeImmZeroOperand(Inst, Base, Address, Decoder); |
398 | 269 | } |
399 | | |
400 | | static DecodeStatus decodeMemRI34Operands(MCInst *Inst, uint64_t Imm, |
401 | | int64_t Address, const void *Decoder) |
402 | 191 | { |
403 | | // Decode the memri34 field (imm, reg), which has the low 34-bits as the |
404 | | // displacement, and the next 5 bits as the register #. |
405 | 191 | uint64_t Base = Imm >> 34; |
406 | 191 | uint64_t Disp = Imm & 0x3FFFFFFFFUL; |
407 | | |
408 | 191 | MCOperand_CreateImm0(Inst, (SignExtend64(Disp, 34))); |
409 | 191 | MCOperand_CreateReg0(Inst, (RRegsNoR0[Base])); |
410 | 191 | return MCDisassembler_Success; |
411 | 191 | } |
412 | | |
413 | | static DecodeStatus decodeSPE8Operands(MCInst *Inst, uint64_t Imm, |
414 | | int64_t Address, const void *Decoder) |
415 | 0 | { |
416 | | // Decode the spe8disp field (imm, reg), which has the low 5-bits as the |
417 | | // displacement with 8-byte aligned, and the next 5 bits as the register #. |
418 | |
|
419 | 0 | uint64_t Base = Imm >> 5; |
420 | 0 | uint64_t Disp = Imm & 0x1F; |
421 | |
|
422 | 0 | MCOperand_CreateImm0(Inst, (Disp << 3)); |
423 | 0 | MCOperand_CreateReg0(Inst, (RRegsNoR0[Base])); |
424 | 0 | return MCDisassembler_Success; |
425 | 0 | } |
426 | | |
427 | | static DecodeStatus decodeSPE4Operands(MCInst *Inst, uint64_t Imm, |
428 | | int64_t Address, const void *Decoder) |
429 | 0 | { |
430 | | // Decode the spe4disp field (imm, reg), which has the low 5-bits as the |
431 | | // displacement with 4-byte aligned, and the next 5 bits as the register #. |
432 | |
|
433 | 0 | uint64_t Base = Imm >> 5; |
434 | 0 | uint64_t Disp = Imm & 0x1F; |
435 | |
|
436 | 0 | MCOperand_CreateImm0(Inst, (Disp << 2)); |
437 | 0 | MCOperand_CreateReg0(Inst, (RRegsNoR0[Base])); |
438 | 0 | return MCDisassembler_Success; |
439 | 0 | } |
440 | | |
441 | | static DecodeStatus decodeSPE2Operands(MCInst *Inst, uint64_t Imm, |
442 | | int64_t Address, const void *Decoder) |
443 | 0 | { |
444 | | // Decode the spe2disp field (imm, reg), which has the low 5-bits as the |
445 | | // displacement with 2-byte aligned, and the next 5 bits as the register #. |
446 | |
|
447 | 0 | uint64_t Base = Imm >> 5; |
448 | 0 | uint64_t Disp = Imm & 0x1F; |
449 | |
|
450 | 0 | MCOperand_CreateImm0(Inst, (Disp << 1)); |
451 | 0 | MCOperand_CreateReg0(Inst, (RRegsNoR0[Base])); |
452 | 0 | return MCDisassembler_Success; |
453 | 0 | } |
454 | | |
455 | | static DecodeStatus decodeCRBitMOperand(MCInst *Inst, uint64_t Imm, |
456 | | int64_t Address, const void *Decoder) |
457 | 269 | { |
458 | | // The cr bit encoding is 0x80 >> cr_reg_num. |
459 | | |
460 | 269 | unsigned Zeros = CountTrailingZeros_32(Imm); |
461 | 269 | if (Zeros >= 8) |
462 | 2 | return MCDisassembler_Fail; |
463 | | |
464 | 267 | MCOperand_CreateReg0(Inst, (CRRegs[7 - Zeros])); |
465 | 267 | return MCDisassembler_Success; |
466 | 269 | } |
467 | | |
468 | | #include "PPCGenDisassemblerTables.inc" |
469 | | |
470 | | DecodeStatus getInstruction(csh ud, const uint8_t *Bytes, size_t BytesLen, |
471 | | MCInst *MI, uint16_t *Size, uint64_t Address, |
472 | | void *Info) |
473 | 70.7k | { |
474 | | // If this is an 8-byte prefixed instruction, handle it here. |
475 | | // Note: prefixed instructions aren't technically 8-byte entities - the |
476 | | // prefix |
477 | | // appears in memory at an address 4 bytes prior to that of the base |
478 | | // instruction regardless of endianness. So we read the two pieces and |
479 | | // rebuild the 8-byte instruction. |
480 | | // TODO: In this function we call decodeInstruction several times with |
481 | | // different decoder tables. It may be possible to only call once by |
482 | | // looking at the top 6 bits of the instruction. |
483 | 70.7k | if (PPC_getFeatureBits(MI->csh->mode, PPC_FeaturePrefixInstrs) && |
484 | 70.7k | BytesLen >= 8) { |
485 | 68.2k | uint32_t Prefix = readBytes32(MI, Bytes); |
486 | 68.2k | uint32_t BaseInst = readBytes32(MI, Bytes + 4); |
487 | 68.2k | uint64_t Inst = BaseInst | (uint64_t)Prefix << 32; |
488 | 68.2k | DecodeStatus result = |
489 | 68.2k | decodeInstruction_4(DecoderTable64, MI, Inst, Address); |
490 | 68.2k | if (result != MCDisassembler_Fail) { |
491 | 697 | *Size = 8; |
492 | 697 | return result; |
493 | 697 | } |
494 | 68.2k | } |
495 | | |
496 | | // Get the four bytes of the instruction. |
497 | 70.0k | *Size = 4; |
498 | 70.0k | if (BytesLen < 4) { |
499 | 778 | *Size = 0; |
500 | 778 | return MCDisassembler_Fail; |
501 | 778 | } |
502 | | |
503 | | // Read the instruction in the proper endianness. |
504 | 69.2k | uint64_t Inst = readBytes32(MI, Bytes); |
505 | | |
506 | 69.2k | if (PPC_getFeatureBits(MI->csh->mode, PPC_FeatureQPX)) { |
507 | 32.6k | DecodeStatus result = decodeInstruction_4(DecoderTableQPX32, MI, |
508 | 32.6k | Inst, Address); |
509 | 32.6k | if (result != MCDisassembler_Fail) |
510 | 3.72k | return result; |
511 | 36.5k | } else if (PPC_getFeatureBits(MI->csh->mode, PPC_FeatureSPE)) { |
512 | 0 | DecodeStatus result = decodeInstruction_4(DecoderTableSPE32, MI, |
513 | 0 | Inst, Address); |
514 | 0 | if (result != MCDisassembler_Fail) |
515 | 0 | return result; |
516 | 36.5k | } else if (PPC_getFeatureBits(MI->csh->mode, PPC_FeaturePS)) { |
517 | 17.8k | DecodeStatus result = decodeInstruction_4(DecoderTablePS32, MI, |
518 | 17.8k | Inst, Address); |
519 | 17.8k | if (result != MCDisassembler_Fail) |
520 | 1.33k | return result; |
521 | 17.8k | } |
522 | | |
523 | 64.1k | return decodeInstruction_4(DecoderTable32, MI, Inst, Address); |
524 | 69.2k | } |
525 | | |
526 | | DecodeStatus PPC_LLVM_getInstruction(csh handle, const uint8_t *Bytes, |
527 | | size_t BytesLen, MCInst *MI, |
528 | | uint16_t *Size, uint64_t Address, |
529 | | void *Info) |
530 | 70.7k | { |
531 | 70.7k | return getInstruction(handle, Bytes, BytesLen, MI, Size, Address, Info); |
532 | 70.7k | } |