/src/capstonev5/arch/PowerPC/PPCDisassembler.c
Line | Count | Source (jump to first uncovered line) |
1 | | //===------ PPCDisassembler.cpp - Disassembler for PowerPC ------*- C++ -*-===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | |
10 | | /* Capstone Disassembly Engine */ |
11 | | /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */ |
12 | | |
13 | | #ifdef CAPSTONE_HAS_POWERPC |
14 | | |
15 | | #include <stdio.h> // DEBUG |
16 | | #include <stdlib.h> |
17 | | #include <string.h> |
18 | | |
19 | | #include "../../cs_priv.h" |
20 | | #include "../../utils.h" |
21 | | |
22 | | #include "PPCDisassembler.h" |
23 | | |
24 | | #include "../../MCInst.h" |
25 | | #include "../../MCInstrDesc.h" |
26 | | #include "../../MCFixedLenDisassembler.h" |
27 | | #include "../../MCRegisterInfo.h" |
28 | | #include "../../MCDisassembler.h" |
29 | | #include "../../MathExtras.h" |
30 | | |
31 | | #define GET_REGINFO_ENUM |
32 | | #include "PPCGenRegisterInfo.inc" |
33 | | |
34 | | |
35 | | // FIXME: These can be generated by TableGen from the existing register |
36 | | // encoding values! |
37 | | |
38 | | static const unsigned CRRegs[] = { |
39 | | PPC_CR0, PPC_CR1, PPC_CR2, PPC_CR3, |
40 | | PPC_CR4, PPC_CR5, PPC_CR6, PPC_CR7 |
41 | | }; |
42 | | |
43 | | static const unsigned CRBITRegs[] = { |
44 | | PPC_CR0LT, PPC_CR0GT, PPC_CR0EQ, PPC_CR0UN, |
45 | | PPC_CR1LT, PPC_CR1GT, PPC_CR1EQ, PPC_CR1UN, |
46 | | PPC_CR2LT, PPC_CR2GT, PPC_CR2EQ, PPC_CR2UN, |
47 | | PPC_CR3LT, PPC_CR3GT, PPC_CR3EQ, PPC_CR3UN, |
48 | | PPC_CR4LT, PPC_CR4GT, PPC_CR4EQ, PPC_CR4UN, |
49 | | PPC_CR5LT, PPC_CR5GT, PPC_CR5EQ, PPC_CR5UN, |
50 | | PPC_CR6LT, PPC_CR6GT, PPC_CR6EQ, PPC_CR6UN, |
51 | | PPC_CR7LT, PPC_CR7GT, PPC_CR7EQ, PPC_CR7UN |
52 | | }; |
53 | | |
54 | | static const unsigned FRegs[] = { |
55 | | PPC_F0, PPC_F1, PPC_F2, PPC_F3, |
56 | | PPC_F4, PPC_F5, PPC_F6, PPC_F7, |
57 | | PPC_F8, PPC_F9, PPC_F10, PPC_F11, |
58 | | PPC_F12, PPC_F13, PPC_F14, PPC_F15, |
59 | | PPC_F16, PPC_F17, PPC_F18, PPC_F19, |
60 | | PPC_F20, PPC_F21, PPC_F22, PPC_F23, |
61 | | PPC_F24, PPC_F25, PPC_F26, PPC_F27, |
62 | | PPC_F28, PPC_F29, PPC_F30, PPC_F31 |
63 | | }; |
64 | | |
65 | | static const unsigned VFRegs[] = { |
66 | | PPC_VF0, PPC_VF1, PPC_VF2, PPC_VF3, |
67 | | PPC_VF4, PPC_VF5, PPC_VF6, PPC_VF7, |
68 | | PPC_VF8, PPC_VF9, PPC_VF10, PPC_VF11, |
69 | | PPC_VF12, PPC_VF13, PPC_VF14, PPC_VF15, |
70 | | PPC_VF16, PPC_VF17, PPC_VF18, PPC_VF19, |
71 | | PPC_VF20, PPC_VF21, PPC_VF22, PPC_VF23, |
72 | | PPC_VF24, PPC_VF25, PPC_VF26, PPC_VF27, |
73 | | PPC_VF28, PPC_VF29, PPC_VF30, PPC_VF31 |
74 | | }; |
75 | | |
76 | | static const unsigned VRegs[] = { |
77 | | PPC_V0, PPC_V1, PPC_V2, PPC_V3, |
78 | | PPC_V4, PPC_V5, PPC_V6, PPC_V7, |
79 | | PPC_V8, PPC_V9, PPC_V10, PPC_V11, |
80 | | PPC_V12, PPC_V13, PPC_V14, PPC_V15, |
81 | | PPC_V16, PPC_V17, PPC_V18, PPC_V19, |
82 | | PPC_V20, PPC_V21, PPC_V22, PPC_V23, |
83 | | PPC_V24, PPC_V25, PPC_V26, PPC_V27, |
84 | | PPC_V28, PPC_V29, PPC_V30, PPC_V31 |
85 | | }; |
86 | | |
87 | | static const unsigned VSRegs[] = { |
88 | | PPC_VSL0, PPC_VSL1, PPC_VSL2, PPC_VSL3, |
89 | | PPC_VSL4, PPC_VSL5, PPC_VSL6, PPC_VSL7, |
90 | | PPC_VSL8, PPC_VSL9, PPC_VSL10, PPC_VSL11, |
91 | | PPC_VSL12, PPC_VSL13, PPC_VSL14, PPC_VSL15, |
92 | | PPC_VSL16, PPC_VSL17, PPC_VSL18, PPC_VSL19, |
93 | | PPC_VSL20, PPC_VSL21, PPC_VSL22, PPC_VSL23, |
94 | | PPC_VSL24, PPC_VSL25, PPC_VSL26, PPC_VSL27, |
95 | | PPC_VSL28, PPC_VSL29, PPC_VSL30, PPC_VSL31, |
96 | | |
97 | | PPC_V0, PPC_V1, PPC_V2, PPC_V3, |
98 | | PPC_V4, PPC_V5, PPC_V6, PPC_V7, |
99 | | PPC_V8, PPC_V9, PPC_V10, PPC_V11, |
100 | | PPC_V12, PPC_V13, PPC_V14, PPC_V15, |
101 | | PPC_V16, PPC_V17, PPC_V18, PPC_V19, |
102 | | PPC_V20, PPC_V21, PPC_V22, PPC_V23, |
103 | | PPC_V24, PPC_V25, PPC_V26, PPC_V27, |
104 | | PPC_V28, PPC_V29, PPC_V30, PPC_V31 |
105 | | }; |
106 | | |
107 | | static const unsigned VSFRegs[] = { |
108 | | PPC_F0, PPC_F1, PPC_F2, PPC_F3, |
109 | | PPC_F4, PPC_F5, PPC_F6, PPC_F7, |
110 | | PPC_F8, PPC_F9, PPC_F10, PPC_F11, |
111 | | PPC_F12, PPC_F13, PPC_F14, PPC_F15, |
112 | | PPC_F16, PPC_F17, PPC_F18, PPC_F19, |
113 | | PPC_F20, PPC_F21, PPC_F22, PPC_F23, |
114 | | PPC_F24, PPC_F25, PPC_F26, PPC_F27, |
115 | | PPC_F28, PPC_F29, PPC_F30, PPC_F31, |
116 | | |
117 | | PPC_VF0, PPC_VF1, PPC_VF2, PPC_VF3, |
118 | | PPC_VF4, PPC_VF5, PPC_VF6, PPC_VF7, |
119 | | PPC_VF8, PPC_VF9, PPC_VF10, PPC_VF11, |
120 | | PPC_VF12, PPC_VF13, PPC_VF14, PPC_VF15, |
121 | | PPC_VF16, PPC_VF17, PPC_VF18, PPC_VF19, |
122 | | PPC_VF20, PPC_VF21, PPC_VF22, PPC_VF23, |
123 | | PPC_VF24, PPC_VF25, PPC_VF26, PPC_VF27, |
124 | | PPC_VF28, PPC_VF29, PPC_VF30, PPC_VF31 |
125 | | }; |
126 | | |
127 | | static const unsigned VSSRegs[] = { |
128 | | PPC_F0, PPC_F1, PPC_F2, PPC_F3, |
129 | | PPC_F4, PPC_F5, PPC_F6, PPC_F7, |
130 | | PPC_F8, PPC_F9, PPC_F10, PPC_F11, |
131 | | PPC_F12, PPC_F13, PPC_F14, PPC_F15, |
132 | | PPC_F16, PPC_F17, PPC_F18, PPC_F19, |
133 | | PPC_F20, PPC_F21, PPC_F22, PPC_F23, |
134 | | PPC_F24, PPC_F25, PPC_F26, PPC_F27, |
135 | | PPC_F28, PPC_F29, PPC_F30, PPC_F31, |
136 | | |
137 | | PPC_VF0, PPC_VF1, PPC_VF2, PPC_VF3, |
138 | | PPC_VF4, PPC_VF5, PPC_VF6, PPC_VF7, |
139 | | PPC_VF8, PPC_VF9, PPC_VF10, PPC_VF11, |
140 | | PPC_VF12, PPC_VF13, PPC_VF14, PPC_VF15, |
141 | | PPC_VF16, PPC_VF17, PPC_VF18, PPC_VF19, |
142 | | PPC_VF20, PPC_VF21, PPC_VF22, PPC_VF23, |
143 | | PPC_VF24, PPC_VF25, PPC_VF26, PPC_VF27, |
144 | | PPC_VF28, PPC_VF29, PPC_VF30, PPC_VF31 |
145 | | }; |
146 | | |
147 | | static const unsigned GPRegs[] = { |
148 | | PPC_R0, PPC_R1, PPC_R2, PPC_R3, |
149 | | PPC_R4, PPC_R5, PPC_R6, PPC_R7, |
150 | | PPC_R8, PPC_R9, PPC_R10, PPC_R11, |
151 | | PPC_R12, PPC_R13, PPC_R14, PPC_R15, |
152 | | PPC_R16, PPC_R17, PPC_R18, PPC_R19, |
153 | | PPC_R20, PPC_R21, PPC_R22, PPC_R23, |
154 | | PPC_R24, PPC_R25, PPC_R26, PPC_R27, |
155 | | PPC_R28, PPC_R29, PPC_R30, PPC_R31 |
156 | | }; |
157 | | |
158 | | static const unsigned GP0Regs[] = { |
159 | | PPC_ZERO, PPC_R1, PPC_R2, PPC_R3, |
160 | | PPC_R4, PPC_R5, PPC_R6, PPC_R7, |
161 | | PPC_R8, PPC_R9, PPC_R10, PPC_R11, |
162 | | PPC_R12, PPC_R13, PPC_R14, PPC_R15, |
163 | | PPC_R16, PPC_R17, PPC_R18, PPC_R19, |
164 | | PPC_R20, PPC_R21, PPC_R22, PPC_R23, |
165 | | PPC_R24, PPC_R25, PPC_R26, PPC_R27, |
166 | | PPC_R28, PPC_R29, PPC_R30, PPC_R31 |
167 | | }; |
168 | | |
169 | | static const unsigned G8Regs[] = { |
170 | | PPC_X0, PPC_X1, PPC_X2, PPC_X3, |
171 | | PPC_X4, PPC_X5, PPC_X6, PPC_X7, |
172 | | PPC_X8, PPC_X9, PPC_X10, PPC_X11, |
173 | | PPC_X12, PPC_X13, PPC_X14, PPC_X15, |
174 | | PPC_X16, PPC_X17, PPC_X18, PPC_X19, |
175 | | PPC_X20, PPC_X21, PPC_X22, PPC_X23, |
176 | | PPC_X24, PPC_X25, PPC_X26, PPC_X27, |
177 | | PPC_X28, PPC_X29, PPC_X30, PPC_X31 |
178 | | }; |
179 | | |
180 | | static const unsigned G80Regs[] = { |
181 | | PPC_ZERO8, PPC_X1, PPC_X2, PPC_X3, |
182 | | PPC_X4, PPC_X5, PPC_X6, PPC_X7, |
183 | | PPC_X8, PPC_X9, PPC_X10, PPC_X11, |
184 | | PPC_X12, PPC_X13, PPC_X14, PPC_X15, |
185 | | PPC_X16, PPC_X17, PPC_X18, PPC_X19, |
186 | | PPC_X20, PPC_X21, PPC_X22, PPC_X23, |
187 | | PPC_X24, PPC_X25, PPC_X26, PPC_X27, |
188 | | PPC_X28, PPC_X29, PPC_X30, PPC_X31 |
189 | | }; |
190 | | |
191 | | static const unsigned QFRegs[] = { |
192 | | PPC_QF0, PPC_QF1, PPC_QF2, PPC_QF3, |
193 | | PPC_QF4, PPC_QF5, PPC_QF6, PPC_QF7, |
194 | | PPC_QF8, PPC_QF9, PPC_QF10, PPC_QF11, |
195 | | PPC_QF12, PPC_QF13, PPC_QF14, PPC_QF15, |
196 | | PPC_QF16, PPC_QF17, PPC_QF18, PPC_QF19, |
197 | | PPC_QF20, PPC_QF21, PPC_QF22, PPC_QF23, |
198 | | PPC_QF24, PPC_QF25, PPC_QF26, PPC_QF27, |
199 | | PPC_QF28, PPC_QF29, PPC_QF30, PPC_QF31 |
200 | | }; |
201 | | |
202 | | static const unsigned SPERegs[] = { |
203 | | PPC_S0, PPC_S1, PPC_S2, PPC_S3, |
204 | | PPC_S4, PPC_S5, PPC_S6, PPC_S7, |
205 | | PPC_S8, PPC_S9, PPC_S10, PPC_S11, |
206 | | PPC_S12, PPC_S13, PPC_S14, PPC_S15, |
207 | | PPC_S16, PPC_S17, PPC_S18, PPC_S19, |
208 | | PPC_S20, PPC_S21, PPC_S22, PPC_S23, |
209 | | PPC_S24, PPC_S25, PPC_S26, PPC_S27, |
210 | | PPC_S28, PPC_S29, PPC_S30, PPC_S31 |
211 | | }; |
212 | | |
213 | | #if 0 |
214 | | static uint64_t getFeatureBits(int feature) |
215 | | { |
216 | | // enable all features |
217 | | return (uint64_t)-1; |
218 | | } |
219 | | #endif |
220 | | |
221 | | static DecodeStatus decodeRegisterClass(MCInst *Inst, uint64_t RegNo, |
222 | | const unsigned *Regs, size_t RegsLen) |
223 | 136k | { |
224 | 136k | if (RegNo >= RegsLen / sizeof(unsigned)) { |
225 | 0 | return MCDisassembler_Fail; |
226 | 0 | } |
227 | 136k | MCOperand_CreateReg0(Inst, Regs[RegNo]); |
228 | 136k | return MCDisassembler_Success; |
229 | 136k | } |
230 | | |
231 | | static DecodeStatus DecodeCRRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
232 | | uint64_t Address, const void *Decoder) |
233 | 4.67k | { |
234 | 4.67k | return decodeRegisterClass(Inst, RegNo, CRRegs, sizeof(CRRegs)); |
235 | 4.67k | } |
236 | | |
237 | | #if 0 |
238 | | static DecodeStatus DecodeCRRC0RegisterClass(MCInst *Inst, uint64_t RegNo, |
239 | | uint64_t Address, const void *Decoder) |
240 | | { |
241 | | return decodeRegisterClass(Inst, RegNo, CRRegs, sizeof(CRRegs)); |
242 | | } |
243 | | #endif |
244 | | |
245 | | static DecodeStatus DecodeCRBITRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
246 | | uint64_t Address, const void *Decoder) |
247 | 9.15k | { |
248 | 9.15k | return decodeRegisterClass(Inst, RegNo, CRBITRegs, sizeof(CRBITRegs)); |
249 | 9.15k | } |
250 | | |
251 | | static DecodeStatus DecodeF4RCRegisterClass(MCInst *Inst, uint64_t RegNo, |
252 | | uint64_t Address, const void *Decoder) |
253 | 2.75k | { |
254 | 2.75k | return decodeRegisterClass(Inst, RegNo, FRegs, sizeof(FRegs)); |
255 | 2.75k | } |
256 | | |
257 | | static DecodeStatus DecodeF8RCRegisterClass(MCInst *Inst, uint64_t RegNo, |
258 | | uint64_t Address, const void *Decoder) |
259 | 6.39k | { |
260 | 6.39k | return decodeRegisterClass(Inst, RegNo, FRegs, sizeof(FRegs)); |
261 | 6.39k | } |
262 | | |
263 | | static DecodeStatus DecodeVFRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
264 | | uint64_t Address, const void *Decoder) |
265 | 210 | { |
266 | 210 | return decodeRegisterClass(Inst, RegNo, VFRegs, sizeof(VFRegs)); |
267 | 210 | } |
268 | | |
269 | | static DecodeStatus DecodeVRRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
270 | | uint64_t Address, const void *Decoder) |
271 | 5.64k | { |
272 | 5.64k | return decodeRegisterClass(Inst, RegNo, VRegs, sizeof(VRegs)); |
273 | 5.64k | } |
274 | | |
275 | | static DecodeStatus DecodeVSRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
276 | | uint64_t Address, const void *Decoder) |
277 | 11.3k | { |
278 | 11.3k | return decodeRegisterClass(Inst, RegNo, VSRegs, sizeof(VSRegs)); |
279 | 11.3k | } |
280 | | |
281 | | static DecodeStatus DecodeVSFRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
282 | | uint64_t Address, const void *Decoder) |
283 | 1.70k | { |
284 | 1.70k | return decodeRegisterClass(Inst, RegNo, VSFRegs, sizeof(VSFRegs)); |
285 | 1.70k | } |
286 | | |
287 | | static DecodeStatus DecodeVSSRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
288 | | uint64_t Address, const void *Decoder) |
289 | 1.02k | { |
290 | 1.02k | return decodeRegisterClass(Inst, RegNo, VSSRegs, sizeof(VSSRegs)); |
291 | 1.02k | } |
292 | | |
293 | | static DecodeStatus DecodeGPRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
294 | | uint64_t Address, const void *Decoder) |
295 | 60.8k | { |
296 | 60.8k | return decodeRegisterClass(Inst, RegNo, GPRegs, sizeof(GPRegs)); |
297 | 60.8k | } |
298 | | |
299 | | static DecodeStatus DecodeGPRC_NOR0RegisterClass(MCInst *Inst, uint64_t RegNo, |
300 | | uint64_t Address, const void *Decoder) |
301 | 4.59k | { |
302 | 4.59k | return decodeRegisterClass(Inst, RegNo, GP0Regs, sizeof(GP0Regs)); |
303 | 4.59k | } |
304 | | |
305 | | static DecodeStatus DecodeG8RCRegisterClass(MCInst *Inst, uint64_t RegNo, |
306 | | uint64_t Address, const void *Decoder) |
307 | 13.7k | { |
308 | 13.7k | return decodeRegisterClass(Inst, RegNo, G8Regs, sizeof(G8Regs)); |
309 | 13.7k | } |
310 | | |
311 | | static DecodeStatus DecodeG8RC_NOX0RegisterClass(MCInst *Inst, uint64_t RegNo, |
312 | | uint64_t Address, const void *Decoder) |
313 | 56 | { |
314 | 56 | return decodeRegisterClass(Inst, RegNo, G80Regs, sizeof(G80Regs)); |
315 | 56 | } |
316 | | |
317 | 2.70k | #define DecodePointerLikeRegClass0 DecodeGPRCRegisterClass |
318 | 3.10k | #define DecodePointerLikeRegClass1 DecodeGPRC_NOR0RegisterClass |
319 | | |
320 | | static DecodeStatus DecodeQFRCRegisterClass(MCInst *Inst, uint64_t RegNo, |
321 | | uint64_t Address, const void *Decoder) |
322 | 14.4k | { |
323 | 14.4k | return decodeRegisterClass(Inst, RegNo, QFRegs, sizeof(QFRegs)); |
324 | 14.4k | } |
325 | | |
326 | | static DecodeStatus DecodeSPE4RCRegisterClass(MCInst *Inst, uint64_t RegNo, |
327 | | uint64_t Address, const void *Decoder) |
328 | 0 | { |
329 | 0 | return decodeRegisterClass(Inst, RegNo, GPRegs, sizeof(GPRegs)); |
330 | 0 | } |
331 | | |
332 | | static DecodeStatus DecodeSPERCRegisterClass(MCInst *Inst, uint64_t RegNo, |
333 | | uint64_t Address, const void *Decoder) |
334 | 0 | { |
335 | 0 | return decodeRegisterClass(Inst, RegNo, SPERegs, sizeof(SPERegs)); |
336 | 0 | } |
337 | | |
338 | 1.16k | #define DecodeQSRCRegisterClass DecodeQFRCRegisterClass |
339 | 7.98k | #define DecodeQBRCRegisterClass DecodeQFRCRegisterClass |
340 | | |
341 | | static DecodeStatus decodeUImmOperand(MCInst *Inst, uint64_t Imm, |
342 | | int64_t Address, const void *Decoder, unsigned N) |
343 | 37.5k | { |
344 | | //assert(isUInt<N>(Imm) && "Invalid immediate"); |
345 | 37.5k | MCOperand_CreateImm0(Inst, Imm); |
346 | | |
347 | 37.5k | return MCDisassembler_Success; |
348 | 37.5k | } |
349 | | |
350 | | static DecodeStatus decodeSImmOperand(MCInst *Inst, uint64_t Imm, |
351 | | int64_t Address, const void *Decoder, unsigned N) |
352 | 10.5k | { |
353 | | // assert(isUInt<N>(Imm) && "Invalid immediate"); |
354 | 10.5k | MCOperand_CreateImm0(Inst, SignExtend64(Imm, N)); |
355 | | |
356 | 10.5k | return MCDisassembler_Success; |
357 | 10.5k | } |
358 | | |
359 | | |
360 | | #define GET_INSTRINFO_ENUM |
361 | | #include "PPCGenInstrInfo.inc" |
362 | | |
363 | | static DecodeStatus decodeMemRIOperands(MCInst *Inst, uint64_t Imm, |
364 | | int64_t Address, const void *Decoder) |
365 | 8.84k | { |
366 | | // Decode the memri field (imm, reg), which has the low 16-bits as the |
367 | | // displacement and the next 5 bits as the register #. |
368 | | |
369 | 8.84k | uint64_t Base = Imm >> 16; |
370 | 8.84k | uint64_t Disp = Imm & 0xFFFF; |
371 | | |
372 | | // assert(Base < 32 && "Invalid base register"); |
373 | 8.84k | if (Base >= 32) |
374 | 0 | return MCDisassembler_Fail; |
375 | | |
376 | 8.84k | switch (MCInst_getOpcode(Inst)) { |
377 | 3.90k | default: break; |
378 | 3.90k | case PPC_LBZU: |
379 | 746 | case PPC_LHAU: |
380 | 1.49k | case PPC_LHZU: |
381 | 2.54k | case PPC_LWZU: |
382 | 2.73k | case PPC_LFSU: |
383 | 3.03k | case PPC_LFDU: |
384 | | // Add the tied output operand. |
385 | 3.03k | MCOperand_CreateReg0(Inst, GP0Regs[Base]); |
386 | 3.03k | break; |
387 | 251 | case PPC_STBU: |
388 | 747 | case PPC_STHU: |
389 | 1.01k | case PPC_STWU: |
390 | 1.27k | case PPC_STFSU: |
391 | 1.90k | case PPC_STFDU: |
392 | 1.90k | MCInst_insert0(Inst, 0, MCOperand_CreateReg1(Inst, GP0Regs[Base])); |
393 | 1.90k | break; |
394 | 8.84k | } |
395 | | |
396 | 8.84k | MCOperand_CreateImm0(Inst, SignExtend64(Disp, 16)); |
397 | 8.84k | MCOperand_CreateReg0(Inst, GP0Regs[Base]); |
398 | | |
399 | 8.84k | return MCDisassembler_Success; |
400 | 8.84k | } |
401 | | |
402 | | static DecodeStatus decodeMemRIXOperands(MCInst *Inst, uint64_t Imm, |
403 | | int64_t Address, const void *Decoder) |
404 | 876 | { |
405 | | // Decode the memrix field (imm, reg), which has the low 14-bits as the |
406 | | // displacement and the next 5 bits as the register #. |
407 | | |
408 | 876 | uint64_t Base = Imm >> 14; |
409 | 876 | uint64_t Disp = Imm & 0x3FFF; |
410 | | |
411 | | // assert(Base < 32 && "Invalid base register"); |
412 | 876 | if (Base >= 32) |
413 | 0 | return MCDisassembler_Fail; |
414 | | |
415 | 876 | if (MCInst_getOpcode(Inst) == PPC_LDU) |
416 | | // Add the tied output operand. |
417 | 257 | MCOperand_CreateReg0(Inst, GP0Regs[Base]); |
418 | 619 | else if (MCInst_getOpcode(Inst) == PPC_STDU) |
419 | 89 | MCInst_insert0(Inst, 0, MCOperand_CreateReg1(Inst, GP0Regs[Base])); |
420 | | |
421 | 876 | MCOperand_CreateImm0(Inst, SignExtend64(Disp << 2, 16)); |
422 | 876 | MCOperand_CreateReg0(Inst, GP0Regs[Base]); |
423 | | |
424 | 876 | return MCDisassembler_Success; |
425 | 876 | } |
426 | | |
427 | | static DecodeStatus decodeMemRIX16Operands(MCInst *Inst, uint64_t Imm, |
428 | | int64_t Address, const void *Decoder) |
429 | 101 | { |
430 | | // Decode the memrix16 field (imm, reg), which has the low 12-bits as the |
431 | | // displacement with 16-byte aligned, and the next 5 bits as the register #. |
432 | | |
433 | 101 | uint64_t Base = Imm >> 12; |
434 | 101 | uint64_t Disp = Imm & 0xFFF; |
435 | | |
436 | | // assert(Base < 32 && "Invalid base register"); |
437 | 101 | if (Base >= 32) |
438 | 0 | return MCDisassembler_Fail; |
439 | | |
440 | 101 | MCOperand_CreateImm0(Inst, SignExtend64(Disp << 4, 16)); |
441 | 101 | MCOperand_CreateReg0(Inst, GP0Regs[Base]); |
442 | | |
443 | 101 | return MCDisassembler_Success; |
444 | 101 | } |
445 | | |
446 | | static DecodeStatus decodeSPE8Operands(MCInst *Inst, uint64_t Imm, |
447 | | int64_t Address, const void *Decoder) |
448 | 0 | { |
449 | | // Decode the spe8disp field (imm, reg), which has the low 5-bits as the |
450 | | // displacement with 8-byte aligned, and the next 5 bits as the register #. |
451 | |
|
452 | 0 | uint64_t Base = Imm >> 5; |
453 | 0 | uint64_t Disp = Imm & 0x1F; |
454 | | |
455 | | // assert(Base < 32 && "Invalid base register"); |
456 | 0 | if (Base >= 32) |
457 | 0 | return MCDisassembler_Fail; |
458 | | |
459 | 0 | MCOperand_CreateImm0(Inst, Disp << 3); |
460 | 0 | MCOperand_CreateReg0(Inst, GP0Regs[Base]); |
461 | |
|
462 | 0 | return MCDisassembler_Success; |
463 | 0 | } |
464 | | |
465 | | static DecodeStatus decodeSPE4Operands(MCInst *Inst, uint64_t Imm, |
466 | | int64_t Address, const void *Decoder) |
467 | 0 | { |
468 | | // Decode the spe4disp field (imm, reg), which has the low 5-bits as the |
469 | | // displacement with 4-byte aligned, and the next 5 bits as the register #. |
470 | |
|
471 | 0 | uint64_t Base = Imm >> 5; |
472 | 0 | uint64_t Disp = Imm & 0x1F; |
473 | | |
474 | | // assert(Base < 32 && "Invalid base register"); |
475 | 0 | if (Base >= 32) |
476 | 0 | return MCDisassembler_Fail; |
477 | | |
478 | 0 | MCOperand_CreateImm0(Inst, Disp << 2); |
479 | 0 | MCOperand_CreateReg0(Inst, GP0Regs[Base]); |
480 | |
|
481 | 0 | return MCDisassembler_Success; |
482 | 0 | } |
483 | | |
484 | | static DecodeStatus decodeSPE2Operands(MCInst *Inst, uint64_t Imm, |
485 | | int64_t Address, const void *Decoder) |
486 | 0 | { |
487 | | // Decode the spe2disp field (imm, reg), which has the low 5-bits as the |
488 | | // displacement with 2-byte aligned, and the next 5 bits as the register #. |
489 | |
|
490 | 0 | uint64_t Base = Imm >> 5; |
491 | 0 | uint64_t Disp = Imm & 0x1F; |
492 | | |
493 | | // assert(Base < 32 && "Invalid base register"); |
494 | 0 | if (Base >= 32) |
495 | 0 | return MCDisassembler_Fail; |
496 | | |
497 | 0 | MCOperand_CreateImm0(Inst, Disp << 1); |
498 | 0 | MCOperand_CreateReg0(Inst, GP0Regs[Base]); |
499 | |
|
500 | 0 | return MCDisassembler_Success; |
501 | 0 | } |
502 | | |
503 | | static DecodeStatus decodeCRBitMOperand(MCInst *Inst, uint64_t Imm, |
504 | | int64_t Address, const void *Decoder) |
505 | 520 | { |
506 | | // The cr bit encoding is 0x80 >> cr_reg_num. |
507 | | |
508 | 520 | unsigned Zeros = CountTrailingZeros_64(Imm); |
509 | | // assert(Zeros < 8 && "Invalid CR bit value"); |
510 | 520 | if (Zeros >= 8) |
511 | 2 | return MCDisassembler_Fail; |
512 | | |
513 | 518 | MCOperand_CreateReg0(Inst, CRRegs[7 - Zeros]); |
514 | | |
515 | 518 | return MCDisassembler_Success; |
516 | 520 | } |
517 | | |
518 | | #include "PPCGenDisassemblerTables.inc" |
519 | | |
520 | | static DecodeStatus getInstruction(MCInst *MI, |
521 | | const uint8_t *code, size_t code_len, |
522 | | uint16_t *Size, |
523 | | uint64_t Address, MCRegisterInfo *MRI) |
524 | 80.8k | { |
525 | 80.8k | uint32_t insn; |
526 | 80.8k | DecodeStatus result; |
527 | | |
528 | | // Get the four bytes of the instruction. |
529 | 80.8k | if (code_len < 4) { |
530 | | // not enough data |
531 | 804 | *Size = 0; |
532 | 804 | return MCDisassembler_Fail; |
533 | 804 | } |
534 | | |
535 | | // The instruction is big-endian encoded. |
536 | 80.0k | if (MODE_IS_BIG_ENDIAN(MI->csh->mode)) |
537 | 80.0k | insn = ((uint32_t) code[0] << 24) | (code[1] << 16) | |
538 | 80.0k | (code[2] << 8) | (code[3] << 0); |
539 | 0 | else // little endian |
540 | 0 | insn = ((uint32_t) code[3] << 24) | (code[2] << 16) | |
541 | 0 | (code[1] << 8) | (code[0] << 0); |
542 | | |
543 | 80.0k | if (MI->flat_insn->detail) { |
544 | 80.0k | memset(MI->flat_insn->detail, 0, offsetof(cs_detail, ppc) + sizeof(cs_ppc)); |
545 | 80.0k | } |
546 | | |
547 | 80.0k | if (MI->csh->mode & CS_MODE_QPX) { |
548 | 41.5k | result = decodeInstruction_4(DecoderTableQPX32, MI, insn, Address); |
549 | 41.5k | if (result != MCDisassembler_Fail) { |
550 | 4.71k | *Size = 4; |
551 | | |
552 | 4.71k | return result; |
553 | 4.71k | } |
554 | | |
555 | | // failed to decode |
556 | 36.8k | MCInst_clear(MI); |
557 | 38.4k | } else if (MI->csh->mode & CS_MODE_SPE) { |
558 | 0 | result = decodeInstruction_4(DecoderTableSPE32, MI, insn, Address); |
559 | 0 | if (result != MCDisassembler_Fail) { |
560 | 0 | *Size = 4; |
561 | |
|
562 | 0 | return result; |
563 | 0 | } |
564 | | |
565 | | // failed to decode |
566 | 0 | MCInst_clear(MI); |
567 | 38.4k | } else if (MI->csh->mode & CS_MODE_PS) { |
568 | 0 | result = decodeInstruction_4(DecoderTablePS32, MI, insn, Address); |
569 | 0 | if (result != MCDisassembler_Fail) { |
570 | 0 | *Size = 4; |
571 | |
|
572 | 0 | return result; |
573 | 0 | } |
574 | | |
575 | | // failed to decode |
576 | 0 | MCInst_clear(MI); |
577 | 0 | } |
578 | | |
579 | 75.3k | result = decodeInstruction_4(DecoderTable32, MI, insn, Address); |
580 | 75.3k | if (result != MCDisassembler_Fail) { |
581 | 74.9k | *Size = 4; |
582 | | |
583 | 74.9k | return result; |
584 | 74.9k | } |
585 | | |
586 | | // cannot decode, report error |
587 | 351 | MCInst_clear(MI); |
588 | 351 | *Size = 0; |
589 | | |
590 | 351 | return MCDisassembler_Fail; |
591 | 75.3k | } |
592 | | |
593 | | bool PPC_getInstruction(csh ud, const uint8_t *code, size_t code_len, |
594 | | MCInst *instr, uint16_t *size, uint64_t address, void *info) |
595 | 80.8k | { |
596 | 80.8k | DecodeStatus status = getInstruction(instr, |
597 | 80.8k | code, code_len, |
598 | 80.8k | size, |
599 | 80.8k | address, (MCRegisterInfo *)info); |
600 | | |
601 | 80.8k | return status == MCDisassembler_Success; |
602 | 80.8k | } |
603 | | |
604 | | #define GET_REGINFO_MC_DESC |
605 | | #include "PPCGenRegisterInfo.inc" |
606 | | void PPC_init(MCRegisterInfo *MRI) |
607 | 2.59k | { |
608 | | /* |
609 | | InitMCRegisterInfo(PPCRegDesc, 344, |
610 | | RA, PC, |
611 | | PPCMCRegisterClasses, 36, |
612 | | PPCRegUnitRoots, 171, PPCRegDiffLists, PPCLaneMaskLists, PPCRegStrings, PPCRegClassStrings, |
613 | | PPCSubRegIdxLists, 7, |
614 | | PPCSubRegIdxRanges, PPCRegEncodingTable); |
615 | | */ |
616 | | |
617 | 2.59k | MCRegisterInfo_InitMCRegisterInfo(MRI, PPCRegDesc, 344, |
618 | 2.59k | 0, 0, |
619 | 2.59k | PPCMCRegisterClasses, 36, |
620 | 2.59k | 0, 0, |
621 | 2.59k | PPCRegDiffLists, |
622 | 2.59k | 0, |
623 | 2.59k | PPCSubRegIdxLists, 7, |
624 | 2.59k | 0); |
625 | 2.59k | } |
626 | | |
627 | | #endif |