1 /* radare2 - LGPL - Copyright 2013-2019 - pancake */
2
3 #include <r_anal.h>
4 #include <r_lib.h>
5 #include <capstone.h>
6 #include <ppc.h>
7 #include "../../asm/arch/ppc/libvle/vle.h"
8
9 #define SPR_HID0 0x3f0 /* Hardware Implementation Register 0 */
10 #define SPR_HID1 0x3f1 /* Hardware Implementation Register 1 */
11 #define SPR_HID2 0x3f3 /* Hardware Implementation Register 2 */
12 #define SPR_HID4 0x3f4 /* Hardware Implementation Register 4 */
13 #define SPR_HID5 0x3f6 /* Hardware Implementation Register 5 */
14 #define SPR_HID6 0x3f9 /* Hardware Implementation Register 6 */
15
16 struct Getarg {
17 csh handle;
18 cs_insn *insn;
19 int bits;
20 };
21
22 #define INSOPS insn->detail->ppc.op_count
23 #define INSOP(n) insn->detail->ppc.operands[n]
24 #define IMM(x) (ut64)(insn->detail->ppc.operands[x].imm)
25
26 #ifndef PFMT32x
27 #define PFMT32x "lx"
28 #endif
29
mask64(ut64 mb,ut64 me)30 static ut64 mask64(ut64 mb, ut64 me) {
31 ut64 maskmb = UT64_MAX >> mb;
32 ut64 maskme = UT64_MAX << (63 - me);
33 return (mb <= me) ? maskmb & maskme : maskmb | maskme;
34 }
35
mask32(ut32 mb,ut32 me)36 static ut32 mask32(ut32 mb, ut32 me) {
37 ut32 maskmb = UT32_MAX >> mb;
38 ut32 maskme = UT32_MAX << (31 - me);
39 return (mb <= me) ? maskmb & maskme : maskmb | maskme;
40 }
41
cmask64(const char * mb_c,const char * me_c)42 static const char* cmask64(const char *mb_c, const char *me_c) {
43 static char cmask[32];
44 ut64 mb = 0;
45 ut64 me = 0;
46 if (mb_c) {
47 mb = strtol (mb_c, NULL, 16);
48 }
49 if (me_c) {
50 me = strtol (me_c, NULL, 16);
51 }
52 snprintf (cmask, sizeof (cmask), "0x%"PFMT64x"", mask64 (mb, me));
53 return cmask;
54 }
55
cmask32(const char * mb_c,const char * me_c)56 static const char* cmask32(const char *mb_c, const char *me_c) {
57 static char cmask[32];
58 ut32 mb = 0;
59 ut32 me = 0;
60 if (mb_c) {
61 mb = strtol (mb_c, NULL, 16);
62 }
63 if (me_c) {
64 me = strtol (me_c, NULL, 16);
65 }
66 snprintf (cmask, sizeof (cmask), "0x%"PFMT32x"", mask32 (mb, me));
67 return cmask;
68 }
69
getarg2(struct Getarg * gop,int n,const char * setstr)70 static char *getarg2(struct Getarg *gop, int n, const char *setstr) {
71 cs_insn *insn = gop->insn;
72 csh handle = gop->handle;
73 static char words[8][64];
74 cs_ppc_op op;
75
76 if (n < 0 || n >= 8) {
77 return NULL;
78 }
79 op = INSOP (n);
80 switch (op.type) {
81 case PPC_OP_INVALID:
82 words[n][0] = '\0';
83 //strcpy (words[n], "invalid");
84 break;
85 case PPC_OP_REG:
86 snprintf (words[n], sizeof (words[n]),
87 "%s%s", cs_reg_name (handle, op.reg), setstr);
88 break;
89 case PPC_OP_IMM:
90 snprintf (words[n], sizeof (words[n]),
91 "0x%"PFMT64x"%s", (ut64) op.imm, setstr);
92 break;
93 case PPC_OP_MEM:
94 snprintf (words[n], sizeof (words[n]),
95 "%"PFMT64d",%s,+,%s",
96 (ut64) op.mem.disp,
97 cs_reg_name (handle, op.mem.base), setstr);
98 break;
99 case PPC_OP_CRX: // Condition Register field
100 snprintf (words[n], sizeof (words[n]),
101 "%"PFMT64d"%s", (ut64) op.imm, setstr);
102 break;
103 }
104 return words[n];
105 }
106
getarg(struct Getarg * gop,int n)107 static ut64 getarg(struct Getarg *gop, int n) {
108 ut64 value = 0;
109 cs_insn *insn = gop->insn;
110 cs_ppc_op op;
111
112 if (n < 0 || n >= 8) {
113 return 0;
114 }
115
116 op = INSOP (n);
117 switch (op.type) {
118 case PPC_OP_INVALID:
119 break;
120 case PPC_OP_REG:
121 value = op.reg;
122 break;
123 case PPC_OP_IMM:
124 value = (ut64) op.imm;
125 break;
126 case PPC_OP_MEM:
127 value = op.mem.disp + op.mem.base;
128 break;
129 case PPC_OP_CRX: // Condition Register field
130 value = (ut64) op.imm;
131 break;
132 }
133 return value;
134 }
135
getspr(struct Getarg * gop,int n)136 static const char* getspr(struct Getarg *gop, int n) {
137 static char cspr[16];
138 ut32 spr = 0;
139 if (n < 0 || n >= 8) {
140 return NULL;
141 }
142 spr = getarg (gop, 0);
143 switch (spr) {
144 case SPR_HID0:
145 return "hid0";
146 case SPR_HID1:
147 return "hid1";
148 case SPR_HID2:
149 return "hid2";
150 case SPR_HID4:
151 return "hid4";
152 case SPR_HID5:
153 return "hid5";
154 case SPR_HID6:
155 return "hid6";
156 default:
157 snprintf (cspr, sizeof (cspr), "spr_%u", spr);
158 break;
159 }
160 return cspr;
161 }
162
opex(RStrBuf * buf,csh handle,cs_insn * insn)163 static void opex(RStrBuf *buf, csh handle, cs_insn *insn) {
164 int i;
165 PJ *pj = pj_new ();
166 if (!pj) {
167 return;
168 }
169 pj_o (pj);
170 pj_ka (pj, "operands");
171 cs_ppc *x = &insn->detail->ppc;
172 for (i = 0; i < x->op_count; i++) {
173 cs_ppc_op *op = x->operands + i;
174 pj_o (pj);
175 switch (op->type) {
176 case PPC_OP_REG:
177 pj_ks (pj, "type", "reg");
178 pj_ks (pj, "value", cs_reg_name (handle, op->reg));
179 break;
180 case PPC_OP_IMM:
181 pj_ks (pj, "type", "imm");
182 pj_kN (pj, "value", op->imm);
183 break;
184 case PPC_OP_MEM:
185 pj_ks (pj, "type", "mem");
186 if (op->mem.base != PPC_REG_INVALID) {
187 pj_ks (pj, "base", cs_reg_name (handle, op->mem.base));
188 }
189 pj_ki (pj, "disp", op->mem.disp);
190 break;
191 default:
192 pj_ks (pj, "type", "invalid");
193 break;
194 }
195 pj_end (pj); /* o operand */
196 }
197 pj_end (pj); /* a operands */
198 pj_end (pj);
199
200 r_strbuf_init (buf);
201 r_strbuf_append (buf, pj_string (pj));
202 pj_free (pj);
203 }
204
205 #define PPCSPR(n) getspr(&gop, n)
206 #define ARG(n) getarg2(&gop, n, "")
207 #define ARG2(n,m) getarg2(&gop, n, m)
208
set_reg_profile(RAnal * anal)209 static bool set_reg_profile(RAnal *anal) {
210 const char *p = NULL;
211 if (anal->bits == 32) {
212 p =
213 "=PC pc\n"
214 "=SP r1\n"
215 "=BP r31\n"
216 "=SR srr1\n" // status register ??
217 "=SN r3\n" // also for ret
218 "=A0 r3\n" // also for ret
219 "=A1 r4\n"
220 "=A2 r5\n"
221 "=A3 r6\n"
222 "=A4 r7\n"
223 "=A5 r8\n"
224 "=A6 r6\n"
225 "gpr srr0 .32 0 0\n"
226 "gpr srr1 .32 4 0\n"
227 "gpr r0 .32 8 0\n"
228 "gpr r1 .32 12 0\n"
229 "gpr r2 .32 16 0\n"
230 "gpr r3 .32 20 0\n"
231 "gpr r4 .32 24 0\n"
232 "gpr r5 .32 28 0\n"
233 "gpr r6 .32 32 0\n"
234 "gpr r7 .32 36 0\n"
235 "gpr r8 .32 40 0\n"
236 "gpr r9 .32 44 0\n"
237 "gpr r10 .32 48 0\n"
238 "gpr r11 .32 52 0\n"
239 "gpr r12 .32 56 0\n"
240 "gpr r13 .32 60 0\n"
241 "gpr r14 .32 64 0\n"
242 "gpr r15 .32 68 0\n"
243 "gpr r16 .32 72 0\n"
244 "gpr r17 .32 76 0\n"
245 "gpr r18 .32 80 0\n"
246 "gpr r19 .32 84 0\n"
247 "gpr r20 .32 88 0\n"
248 "gpr r21 .32 92 0\n"
249 "gpr r22 .32 96 0\n"
250 "gpr r23 .32 100 0\n"
251 "gpr r24 .32 104 0\n"
252 "gpr r25 .32 108 0\n"
253 "gpr r26 .32 112 0\n"
254 "gpr r27 .32 116 0\n"
255 "gpr r28 .32 120 0\n"
256 "gpr r29 .32 124 0\n"
257 "gpr r30 .32 128 0\n"
258 "gpr r31 .32 132 0\n"
259 "gpr lr .32 136 0\n"
260 "gpr ctr .32 140 0\n"
261 "gpr msr .32 144 0\n"
262 "gpr pc .32 148 0\n"
263 "gpr cr .64 152 0\n"
264 "gpr cr0 .8 152 0\n"
265 "gpr cr1 .8 153 0\n"
266 "gpr cr2 .8 154 0\n"
267 "gpr cr3 .8 155 0\n"
268 "gpr cr4 .8 156 0\n"
269 "gpr cr5 .8 157 0\n"
270 "gpr cr6 .8 158 0\n"
271 "gpr cr7 .8 159 0\n"
272 "gpr xer .32 160 0\n"
273 "gpr mq .32 164 0\n"
274 "gpr fpscr .32 168 0\n"
275 "gpr vrsave .32 172 0\n"
276 "gpr pvr .32 176 0\n"
277 "gpr dccr .32 180 0\n"
278 "gpr iccr .32 184 0\n"
279 "gpr dear .32 188 0\n"
280 "gpr hid0 .32 192 0\n"
281 "gpr hid1 .32 196 0\n"
282 "gpr hid2 .32 200 0\n"
283 "gpr hid3 .32 204 0\n"
284 "gpr hid4 .32 208 0\n"
285 "gpr hid5 .32 212 0\n"
286 "gpr hid6 .32 216 0\n"
287 "gpr ibat0 .64 220 0\n"
288 "gpr ibat1 .64 228 0\n"
289 "gpr ibat2 .64 236 0\n"
290 "gpr ibat3 .64 244 0\n"
291 "gpr ibat0l .32 220 0\n"
292 "gpr ibat1l .32 228 0\n"
293 "gpr ibat2l .32 236 0\n"
294 "gpr ibat3l .32 244 0\n"
295 "gpr ibat0u .32 224 0\n"
296 "gpr ibat1u .32 232 0\n"
297 "gpr ibat2u .32 240 0\n"
298 "gpr ibat3u .32 248 0\n"
299 "gpr dbat0 .64 256 0\n"
300 "gpr dbat1 .64 264 0\n"
301 "gpr dbat2 .64 272 0\n"
302 "gpr dbat3 .64 280 0\n"
303 "gpr dbat0l .32 256 0\n"
304 "gpr dbat1l .32 264 0\n"
305 "gpr dbat2l .32 272 0\n"
306 "gpr dbat3l .32 280 0\n"
307 "gpr dbat0u .32 260 0\n"
308 "gpr dbat1u .32 268 0\n"
309 "gpr dbat2u .32 276 0\n"
310 "gpr dbat3u .32 284 0\n"
311 "gpr mask .32 288 0\n";
312 } else {
313 p =
314 "=PC pc\n"
315 "=SP r1\n"
316 "=SR srr1\n" // status register ??
317 "=SN r0\n" // also for ret
318 "=A0 r3\n" // also for ret
319 "=A1 r4\n"
320 "=A2 r5\n"
321 "=A3 r6\n"
322 "=A4 r7\n"
323 "=A5 r8\n"
324 "=A6 r6\n"
325 "gpr srr0 .64 0 0\n"
326 "gpr srr1 .64 8 0\n"
327 "gpr r0 .64 16 0\n"
328 "gpr r1 .64 24 0\n"
329 "gpr r2 .64 32 0\n"
330 "gpr r3 .64 40 0\n"
331 "gpr r4 .64 48 0\n"
332 "gpr r5 .64 56 0\n"
333 "gpr r6 .64 64 0\n"
334 "gpr r7 .64 72 0\n"
335 "gpr r8 .64 80 0\n"
336 "gpr r9 .64 88 0\n"
337 "gpr r10 .64 96 0\n"
338 "gpr r11 .64 104 0\n"
339 "gpr r12 .64 112 0\n"
340 "gpr r13 .64 120 0\n"
341 "gpr r14 .64 128 0\n"
342 "gpr r15 .64 136 0\n"
343 "gpr r16 .64 144 0\n"
344 "gpr r17 .64 152 0\n"
345 "gpr r18 .64 160 0\n"
346 "gpr r19 .64 168 0\n"
347 "gpr r20 .64 176 0\n"
348 "gpr r21 .64 184 0\n"
349 "gpr r22 .64 192 0\n"
350 "gpr r23 .64 200 0\n"
351 "gpr r24 .64 208 0\n"
352 "gpr r25 .64 216 0\n"
353 "gpr r26 .64 224 0\n"
354 "gpr r27 .64 232 0\n"
355 "gpr r28 .64 240 0\n"
356 "gpr r29 .64 248 0\n"
357 "gpr r30 .64 256 0\n"
358 "gpr r31 .64 264 0\n"
359 "gpr lr .64 272 0\n"
360 "gpr ctr .64 280 0\n"
361 "gpr msr .64 288 0\n"
362 "gpr pc .64 296 0\n"
363 "gpr cr .64 304 0\n"
364 "gpr cr0 .8 304 0\n"
365 "gpr cr1 .8 305 0\n"
366 "gpr cr2 .8 306 0\n"
367 "gpr cr3 .8 307 0\n"
368 "gpr cr4 .8 308 0\n"
369 "gpr cr5 .8 309 0\n"
370 "gpr cr6 .8 310 0\n"
371 "gpr cr7 .8 311 0\n"
372 "gpr xer .64 312 0\n"
373 "gpr mq .64 320 0\n"
374 "gpr fpscr .64 328 0\n"
375 "gpr vrsave .64 336 0\n"
376 "gpr pvr .64 344 0\n"
377 "gpr dccr .32 352 0\n"
378 "gpr iccr .32 356 0\n"
379 "gpr dear .32 360 0\n"
380 "gpr hid0 .64 364 0\n"
381 "gpr hid1 .64 372 0\n"
382 "gpr hid2 .64 380 0\n"
383 "gpr hid3 .64 388 0\n"
384 "gpr hid4 .64 396 0\n"
385 "gpr hid5 .64 404 0\n"
386 "gpr hid6 .64 412 0\n"
387 "gpr ibat0 .64 420 0\n"
388 "gpr ibat1 .64 428 0\n"
389 "gpr ibat2 .64 436 0\n"
390 "gpr ibat3 .64 444 0\n"
391 "gpr ibat0l .32 420 0\n"
392 "gpr ibat1l .32 428 0\n"
393 "gpr ibat2l .32 436 0\n"
394 "gpr ibat3l .32 444 0\n"
395 "gpr ibat0u .32 424 0\n"
396 "gpr ibat1u .32 432 0\n"
397 "gpr ibat2u .32 440 0\n"
398 "gpr ibat3u .32 448 0\n"
399 "gpr dbat0 .64 456 0\n"
400 "gpr dbat1 .64 464 0\n"
401 "gpr dbat2 .64 472 0\n"
402 "gpr dbat3 .64 480 0\n"
403 "gpr dbat0l .32 456 0\n"
404 "gpr dbat1l .32 464 0\n"
405 "gpr dbat2l .32 472 0\n"
406 "gpr dbat3l .32 480 0\n"
407 "gpr dbat0u .32 460 0\n"
408 "gpr dbat1u .32 468 0\n"
409 "gpr dbat2u .32 476 0\n"
410 "gpr dbat3u .32 484 0\n"
411 "gpr mask .64 488 0\n"; //not a real register used on complex functions
412 }
413 return r_reg_set_profile_string (anal->reg, p);
414 }
415
analop_vle(RAnal * a,RAnalOp * op,ut64 addr,const ut8 * buf,int len)416 static int analop_vle(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) {
417 vle_t* instr = NULL;
418 vle_handle handle = {0};
419 op->size = 2;
420 if (len > 1 && !vle_init (&handle, buf, len) && (instr = vle_next (&handle))) {
421 op->size = instr->size;
422 op->type = instr->anal_op;
423 //op->id = instr->type;
424
425 switch (op->type) {
426 case R_ANAL_OP_TYPE_ILL:
427 break;
428 case R_ANAL_OP_TYPE_ADD:
429 break;
430 case R_ANAL_OP_TYPE_AND:
431 break;
432 case R_ANAL_OP_TYPE_CALL:
433 op->jump = addr + instr->fields[instr->n - 1].value;
434 op->fail = addr + op->size;
435 break;
436 case R_ANAL_OP_TYPE_CCALL:
437 op->eob = true;
438 op->jump = addr + instr->fields[instr->n - 1].value;
439 op->fail = addr + op->size;
440 break;
441 case R_ANAL_OP_TYPE_CJMP:
442 op->cond = instr->cond; //R_ANAL_COND_NE;
443 op->eob = true;
444 op->jump = addr + instr->fields[instr->n - 1].value;
445 op->fail = addr + op->size;
446 break;
447 case R_ANAL_OP_TYPE_CMP:
448 break;
449 case R_ANAL_OP_TYPE_JMP:
450 op->jump = addr + instr->fields[instr->n - 1].value;
451 break;
452 case R_ANAL_OP_TYPE_LOAD:
453 break;
454 case R_ANAL_OP_TYPE_MOV:
455 break;
456 case R_ANAL_OP_TYPE_MUL:
457 break;
458 case R_ANAL_OP_TYPE_NOT:
459 break;
460 case R_ANAL_OP_TYPE_OR:
461 break;
462 case R_ANAL_OP_TYPE_ROR:
463 break;
464 case R_ANAL_OP_TYPE_ROL:
465 break;
466 case R_ANAL_OP_TYPE_RCALL:
467 op->eob = true;
468 break;
469 case R_ANAL_OP_TYPE_RET:
470 op->eob = true;
471 break;
472 case R_ANAL_OP_TYPE_RJMP:
473 break;
474 case R_ANAL_OP_TYPE_SHL:
475 break;
476 case R_ANAL_OP_TYPE_SHR:
477 break;
478 case R_ANAL_OP_TYPE_STORE:
479 break;
480 case R_ANAL_OP_TYPE_SUB:
481 break;
482 case R_ANAL_OP_TYPE_SWI:
483 break;
484 case R_ANAL_OP_TYPE_SYNC:
485 break;
486 case R_ANAL_OP_TYPE_TRAP:
487 break;
488 case R_ANAL_OP_TYPE_XOR:
489 break;
490 default:
491 //eprintf ("Missing an R_ANAL_OP_TYPE (%"PFMT64u")\n", op->type);
492 break;
493 }
494 vle_free (instr);
495 return op->size;
496 }
497 return -1;
498 }
499
parse_reg_name(RRegItem * reg,csh handle,cs_insn * insn,int reg_num)500 static int parse_reg_name(RRegItem *reg, csh handle, cs_insn *insn, int reg_num) {
501 if (!reg) {
502 return -1;
503 }
504 switch (INSOP (reg_num).type) {
505 case PPC_OP_REG:
506 reg->name = (char *)cs_reg_name (handle, INSOP (reg_num).reg);
507 break;
508 case PPC_OP_MEM:
509 if (INSOP (reg_num).mem.base != PPC_REG_INVALID) {
510 reg->name = (char *)cs_reg_name (handle, INSOP (reg_num).mem.base);
511 }
512 break;
513 default :
514 break;
515 }
516 return 0;
517 }
518
519 static RRegItem base_regs[4];
520
create_src_dst(RAnalOp * op)521 static void create_src_dst(RAnalOp *op) {
522 op->src[0] = r_anal_value_new ();
523 op->src[1] = r_anal_value_new ();
524 op->src[2] = r_anal_value_new ();
525 op->dst = r_anal_value_new ();
526 ZERO_FILL (base_regs[0]);
527 ZERO_FILL (base_regs[1]);
528 ZERO_FILL (base_regs[2]);
529 ZERO_FILL (base_regs[3]);
530 }
531
set_src_dst(RAnalValue * val,csh * handle,cs_insn * insn,int x)532 static void set_src_dst(RAnalValue *val, csh *handle, cs_insn *insn, int x) {
533 cs_ppc_op ppcop = INSOP (x);
534 parse_reg_name (&base_regs[x], *handle, insn, x);
535 switch (ppcop.type) {
536 case PPC_OP_REG:
537 break;
538 case PPC_OP_MEM:
539 val->delta = ppcop.mem.disp;
540 break;
541 case PPC_OP_IMM:
542 val->imm = ppcop.imm;
543 break;
544 default:
545 break;
546 }
547 val->reg = &base_regs[x];
548 }
549
op_fillval(RAnalOp * op,csh handle,cs_insn * insn)550 static void op_fillval(RAnalOp *op, csh handle, cs_insn *insn) {
551 create_src_dst (op);
552 switch (op->type & R_ANAL_OP_TYPE_MASK) {
553 case R_ANAL_OP_TYPE_MOV:
554 case R_ANAL_OP_TYPE_CMP:
555 case R_ANAL_OP_TYPE_ADD:
556 case R_ANAL_OP_TYPE_SUB:
557 case R_ANAL_OP_TYPE_MUL:
558 case R_ANAL_OP_TYPE_DIV:
559 case R_ANAL_OP_TYPE_SHR:
560 case R_ANAL_OP_TYPE_SHL:
561 case R_ANAL_OP_TYPE_SAL:
562 case R_ANAL_OP_TYPE_SAR:
563 case R_ANAL_OP_TYPE_OR:
564 case R_ANAL_OP_TYPE_AND:
565 case R_ANAL_OP_TYPE_XOR:
566 case R_ANAL_OP_TYPE_NOR:
567 case R_ANAL_OP_TYPE_NOT:
568 case R_ANAL_OP_TYPE_LOAD:
569 case R_ANAL_OP_TYPE_LEA:
570 case R_ANAL_OP_TYPE_ROR:
571 case R_ANAL_OP_TYPE_ROL:
572 case R_ANAL_OP_TYPE_CAST:
573 set_src_dst (op->src[2], &handle, insn, 3);
574 set_src_dst (op->src[1], &handle, insn, 2);
575 set_src_dst (op->src[0], &handle, insn, 1);
576 set_src_dst (op->dst, &handle, insn, 0);
577 break;
578 case R_ANAL_OP_TYPE_STORE:
579 set_src_dst (op->dst, &handle, insn, 1);
580 set_src_dst (op->src[0], &handle, insn, 0);
581 break;
582 }
583 }
584
analop(RAnal * a,RAnalOp * op,ut64 addr,const ut8 * buf,int len,RAnalOpMask mask)585 static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) {
586 static csh handle = 0;
587 static int omode = -1, obits = -1;
588 int n, ret;
589 cs_insn *insn;
590 char *op1;
591 int mode = (a->bits == 64) ? CS_MODE_64 : (a->bits == 32) ? CS_MODE_32 : 0;
592 mode |= a->big_endian ? CS_MODE_BIG_ENDIAN : CS_MODE_LITTLE_ENDIAN;
593
594 if (a->cpu && strncmp (a->cpu, "vle", 3) == 0) {
595 // vle is big-endian only
596 if (!a->big_endian) {
597 return -1;
598 }
599 ret = analop_vle (a, op, addr, buf, len);
600 if (ret >= 0) {
601 return op->size;
602 }
603 }
604
605 if (mode != omode || a->bits != obits) {
606 cs_close (&handle);
607 handle = 0;
608 omode = mode;
609 obits = a->bits;
610 }
611 if (handle == 0) {
612 ret = cs_open (CS_ARCH_PPC, mode, &handle);
613 if (ret != CS_ERR_OK) {
614 return -1;
615 }
616 cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON);
617 }
618 op->size = 4;
619
620 // capstone-next
621 n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn);
622 if (n < 1) {
623 op->type = R_ANAL_OP_TYPE_ILL;
624 } else {
625 if (mask & R_ANAL_OP_MASK_OPEX) {
626 opex (&op->opex, handle, insn);
627 }
628 struct Getarg gop = {
629 .handle = handle,
630 .insn = insn,
631 .bits = a->bits
632 };
633 op->size = insn->size;
634 op->id = insn->id;
635 switch (insn->id) {
636 #if CS_API_MAJOR >= 4
637 case PPC_INS_CMPB:
638 #endif
639 case PPC_INS_CMPD:
640 case PPC_INS_CMPDI:
641 case PPC_INS_CMPLD:
642 case PPC_INS_CMPLDI:
643 case PPC_INS_CMPLW:
644 case PPC_INS_CMPLWI:
645 case PPC_INS_CMPW:
646 case PPC_INS_CMPWI:
647 #if CS_API_MAJOR > 4
648 case PPC_INS_CMP:
649 case PPC_INS_CMPI:
650 #endif
651 op->type = R_ANAL_OP_TYPE_CMP;
652 op->sign = true;
653 if (ARG (2)[0] == '\0') {
654 esilprintf (op, "%s,%s,-,0xff,&,cr0,=", ARG (1), ARG (0));
655 } else {
656 esilprintf (op, "%s,%s,-,0xff,&,%s,=", ARG (2), ARG (1), ARG (0));
657 }
658 break;
659 case PPC_INS_MFLR:
660 op->type = R_ANAL_OP_TYPE_MOV;
661 esilprintf (op, "lr,%s,=", ARG (0));
662 break;
663 case PPC_INS_MTLR:
664 op->type = R_ANAL_OP_TYPE_MOV;
665 esilprintf (op, "%s,lr,=", ARG (0));
666 break;
667 case PPC_INS_MR:
668 case PPC_INS_LI:
669 op->type = R_ANAL_OP_TYPE_MOV;
670 esilprintf (op, "%s,%s,=", ARG (1), ARG (0));
671 break;
672 case PPC_INS_LIS:
673 op->type = R_ANAL_OP_TYPE_MOV;
674 esilprintf (op, "%s0000,%s,=", ARG (1), ARG (0));
675 break;
676 case PPC_INS_CLRLWI:
677 op->type = R_ANAL_OP_TYPE_AND;
678 esilprintf (op, "%s,%s,&,%s,=", ARG (1), cmask32 (ARG (2), "0x1F"), ARG (0));
679 break;
680 case PPC_INS_RLWINM:
681 op->type = R_ANAL_OP_TYPE_ROL;
682 esilprintf (op, "%s,%s,<<<,%s,&,%s,=", ARG (2), ARG (1), cmask32 (ARG (3), ARG (4)), ARG (0));
683 break;
684 case PPC_INS_SC:
685 op->type = R_ANAL_OP_TYPE_SWI;
686 esilprintf (op, "0,$");
687 break;
688 case PPC_INS_EXTSB:
689 op->sign = true;
690 op->type = R_ANAL_OP_TYPE_MOV;
691 if (a->bits == 64) {
692 esilprintf (op, "%s,0x80,&,?{,0xFFFFFFFFFFFFFF00,%s,|,%s,=,}", ARG (1), ARG (1), ARG (0));
693 } else {
694 esilprintf (op, "%s,0x80,&,?{,0xFFFFFF00,%s,|,%s,=,}", ARG (1), ARG (1), ARG (0));
695 }
696 break;
697 case PPC_INS_EXTSH:
698 op->sign = true;
699 if (a->bits == 64) {
700 esilprintf (op, "%s,0x8000,&,?{,0xFFFFFFFFFFFF0000,%s,|,%s,=,}", ARG (1), ARG (1), ARG (0));
701 } else {
702 esilprintf (op, "%s,0x8000,&,?{,0xFFFF0000,%s,|,%s,=,}", ARG (1), ARG (1), ARG (0));
703 }
704 break;
705 case PPC_INS_EXTSW:
706 op->sign = true;
707 esilprintf (op, "%s,0x80000000,&,?{,0xFFFFFFFF00000000,%s,|,%s,=,}", ARG (1), ARG (1), ARG (0));
708 break;
709 case PPC_INS_SYNC:
710 case PPC_INS_ISYNC:
711 case PPC_INS_LWSYNC:
712 case PPC_INS_MSYNC:
713 case PPC_INS_PTESYNC:
714 case PPC_INS_TLBSYNC:
715 case PPC_INS_SLBIA:
716 case PPC_INS_SLBIE:
717 case PPC_INS_SLBMFEE:
718 case PPC_INS_SLBMTE:
719 case PPC_INS_EIEIO:
720 case PPC_INS_NOP:
721 op->type = R_ANAL_OP_TYPE_NOP;
722 esilprintf (op, ",");
723 break;
724 case PPC_INS_STW:
725 case PPC_INS_STWUX:
726 case PPC_INS_STWX:
727 case PPC_INS_STWCX:
728 op->type = R_ANAL_OP_TYPE_STORE;
729 esilprintf (op, "%s,%s", ARG (0), ARG2 (1, "=[4]"));
730 break;
731 case PPC_INS_STWU:
732 op->type = R_ANAL_OP_TYPE_STORE;
733 op1 = ARG (1);
734 op1[strlen (op1) - 1] = 0;
735 esilprintf (op, "%s,%s,=[4],%s=", ARG (0), op1, op1);
736 if (strstr (op1, "r1")) {
737 op->stackop = R_ANAL_STACK_INC;
738 op->stackptr = -atoi (op1);
739 }
740 break;
741 case PPC_INS_STWBRX:
742 op->type = R_ANAL_OP_TYPE_STORE;
743 break;
744 case PPC_INS_STB:
745 op->type = R_ANAL_OP_TYPE_STORE;
746 esilprintf (op, "%s,%s", ARG (0), ARG2 (1, "=[1]"));
747 break;
748 case PPC_INS_STBU:
749 op->type = R_ANAL_OP_TYPE_STORE;
750 op1 = ARG (1);
751 op1[strlen (op1) - 1] = 0;
752 esilprintf (op, "%s,%s,=[1],%s=", ARG (0), op1, op1);
753 break;
754 case PPC_INS_STH:
755 op->type = R_ANAL_OP_TYPE_STORE;
756 esilprintf (op, "%s,%s", ARG (0), ARG2 (1, "=[2]"));
757 break;
758 case PPC_INS_STHU:
759 op->type = R_ANAL_OP_TYPE_STORE;
760 op1 = ARG (1);
761 op1[strlen (op1) - 1] = 0;
762 esilprintf (op, "%s,%s,=[2],%s=", ARG (0), op1, op1);
763 break;
764 case PPC_INS_STD:
765 op->type = R_ANAL_OP_TYPE_STORE;
766 esilprintf (op, "%s,%s", ARG (0), ARG2 (1, "=[8]"));
767 break;
768 case PPC_INS_STDU:
769 op->type = R_ANAL_OP_TYPE_STORE;
770 op1 = ARG (1);
771 op1[strlen (op1) - 1] = 0;
772 esilprintf (op, "%s,%s,=[8],%s=", ARG (0), op1, op1);
773 break;
774 case PPC_INS_LBZ:
775 #if CS_API_MAJOR >= 4
776 case PPC_INS_LBZCIX:
777 #endif
778 case PPC_INS_LBZU:
779 case PPC_INS_LBZUX:
780 op->type = R_ANAL_OP_TYPE_LOAD;
781 op1 = ARG (1);
782 op1[strlen (op1) - 1] = 0;
783 esilprintf (op, "%s,[1],%s,=,%s=", op1, ARG (0), op1);
784 break;
785 case PPC_INS_LBZX:
786 op->type = R_ANAL_OP_TYPE_LOAD;
787 esilprintf (op, "%s,%s,=", ARG2 (1, "[1]"), ARG (0));
788 break;
789 case PPC_INS_LD:
790 case PPC_INS_LDARX:
791 #if CS_API_MAJOR >= 4
792 case PPC_INS_LDCIX:
793 #endif
794 case PPC_INS_LDU:
795 case PPC_INS_LDUX:
796 op->type = R_ANAL_OP_TYPE_LOAD;
797 op1 = ARG (1);
798 op1[strlen (op1) - 1] = 0;
799 esilprintf (op, "%s,[8],%s,=,%s=", op1, ARG (0), op1);
800 break;
801 case PPC_INS_LDX:
802 op->type = R_ANAL_OP_TYPE_LOAD;
803 esilprintf (op, "%s,%s,=", ARG2 (1, "[8]"), ARG (0));
804 break;
805 case PPC_INS_LDBRX:
806 op->type = R_ANAL_OP_TYPE_LOAD;
807 break;
808 case PPC_INS_LFD:
809 case PPC_INS_LFDU:
810 case PPC_INS_LFDUX:
811 case PPC_INS_LFDX:
812 case PPC_INS_LFIWAX:
813 case PPC_INS_LFIWZX:
814 case PPC_INS_LFS:
815 case PPC_INS_LFSU:
816 case PPC_INS_LFSUX:
817 case PPC_INS_LFSX:
818 op->type = R_ANAL_OP_TYPE_LOAD;
819 esilprintf (op, "%s,%s,=", ARG2 (1, "[4]"), ARG (0));
820 break;
821 case PPC_INS_LHA:
822 case PPC_INS_LHAU:
823 case PPC_INS_LHAUX:
824 case PPC_INS_LHAX:
825 case PPC_INS_LHZ:
826 case PPC_INS_LHZU:
827 op->type = R_ANAL_OP_TYPE_LOAD;
828 op1 = ARG (1);
829 op1[strlen (op1) - 1] = 0;
830 esilprintf (op, "%s,[2],%s,=,%s=", op1, ARG (0), op1);
831 break;
832 case PPC_INS_LHBRX:
833 op->type = R_ANAL_OP_TYPE_LOAD;
834 break;
835 case PPC_INS_LWA:
836 case PPC_INS_LWARX:
837 case PPC_INS_LWAUX:
838 case PPC_INS_LWAX:
839 case PPC_INS_LWZ:
840 #if CS_API_MAJOR >= 4
841 case PPC_INS_LWZCIX:
842 #endif
843 case PPC_INS_LWZX:
844 op->type = R_ANAL_OP_TYPE_LOAD;
845 esilprintf (op, "%s,%s,=", ARG2 (1, "[4]"), ARG (0));
846 break;
847 case PPC_INS_LWZU:
848 case PPC_INS_LWZUX:
849 op->type = R_ANAL_OP_TYPE_LOAD;
850 op1 = ARG (1);
851 op1[strlen(op1) - 1] = 0;
852 esilprintf (op, "%s,[4],%s,=,%s=", op1, ARG (0), op1);
853 break;
854 case PPC_INS_LWBRX:
855 op->type = R_ANAL_OP_TYPE_LOAD;
856 break;
857 case PPC_INS_SLW:
858 case PPC_INS_SLWI:
859 op->type = R_ANAL_OP_TYPE_SHL;
860 esilprintf (op, "%s,%s,<<,%s,=", ARG (2), ARG (1), ARG (0));
861 break;
862 case PPC_INS_SRW:
863 case PPC_INS_SRWI:
864 op->type = R_ANAL_OP_TYPE_SHR;
865 esilprintf (op, "%s,%s,>>,%s,=", ARG (2), ARG (1), ARG (0));
866 break;
867 case PPC_INS_MULLI:
868 op->sign = true;
869 case PPC_INS_MULLW:
870 case PPC_INS_MULLD:
871 op->type = R_ANAL_OP_TYPE_MUL;
872 esilprintf (op, "%s,%s,*,%s,=", ARG (2), ARG (1), ARG (0));
873 break;
874 case PPC_INS_SUB:
875 case PPC_INS_SUBC:
876 case PPC_INS_SUBF:
877 case PPC_INS_SUBFIC:
878 case PPC_INS_SUBFZE:
879 op->type = R_ANAL_OP_TYPE_SUB;
880 esilprintf (op, "%s,%s,-,%s,=", ARG (1), ARG (2), ARG (0));
881 break;
882 case PPC_INS_ADD:
883 case PPC_INS_ADDI:
884 op->sign = true;
885 op->type = R_ANAL_OP_TYPE_ADD;
886 esilprintf (op, "%s,%s,+,%s,=", ARG (2), ARG (1), ARG (0));
887 break;
888 case PPC_INS_CRCLR:
889 case PPC_INS_CRSET:
890 case PPC_INS_CRMOVE:
891 case PPC_INS_CRXOR:
892 case PPC_INS_CRNOR:
893 case PPC_INS_CRNOT:
894 // reset conditional bits
895 op->type = R_ANAL_OP_TYPE_MOV;
896 break;
897 case PPC_INS_ADDC:
898 case PPC_INS_ADDIC:
899 op->type = R_ANAL_OP_TYPE_ADD;
900 esilprintf (op, "%s,%s,+,%s,=", ARG (2), ARG (1), ARG (0));
901 break;
902 case PPC_INS_ADDE:
903 case PPC_INS_ADDIS:
904 case PPC_INS_ADDME:
905 case PPC_INS_ADDZE:
906 op->type = R_ANAL_OP_TYPE_ADD;
907 esilprintf (op, "%s,%s,+,%s,=", ARG (2), ARG (1), ARG (0));
908 break;
909 case PPC_INS_MTSPR:
910 op->type = R_ANAL_OP_TYPE_MOV;
911 esilprintf (op, "%s,%s,=", ARG (1), PPCSPR (0));
912 break;
913 case PPC_INS_BCTR: // switch table here
914 op->type = R_ANAL_OP_TYPE_UJMP;
915 esilprintf (op, "ctr,pc,=");
916 break;
917 case PPC_INS_BCTRL: // switch table here
918 op->type = R_ANAL_OP_TYPE_CALL;
919 esilprintf (op, "pc,lr,=,ctr,pc,=");
920 break;
921 case PPC_INS_B:
922 case PPC_INS_BC:
923 case PPC_INS_BA:
924 op->type = R_ANAL_OP_TYPE_CJMP;
925 op->jump = ARG (1)[0] == '\0' ? IMM (0) : IMM (1);
926 op->fail = addr + op->size;
927 switch (insn->detail->ppc.bc) {
928 case PPC_BC_LT:
929 if (ARG (1)[0] == '\0') {
930 esilprintf (op, "0x80,cr0,&,!,!,?{,%s,pc,=,},", ARG (0));
931 } else {
932 esilprintf (op, "0x80,%s,&,!,!,?{,%s,pc,=,},", ARG (0), ARG (1));
933 }
934 break;
935 case PPC_BC_LE:
936 if (ARG (1)[0] == '\0') {
937 esilprintf (op, "0x80,cr0,&,!,!,cr0,!,|,?{,%s,pc,=,},", ARG (0));
938 } else {
939 esilprintf (op, "0x80,%s,&,!,!,0,%s,!,|,?{,%s,pc,=,},", ARG (0), ARG (0), ARG (1));
940 }
941 break;
942 case PPC_BC_EQ:
943 if (ARG (1)[0] == '\0') {
944 esilprintf (op, "cr0,!,?{,%s,pc,=,},", ARG (0));
945 } else {
946 esilprintf (op, "%s,!,?{,%s,pc,=,},", ARG (0), ARG (1));
947 }
948 break;
949 case PPC_BC_GE:
950 if (ARG (1)[0] == '\0') {
951 esilprintf (op, "0x80,cr0,&,!,cr0,!,|,?{,%s,pc,=,},", ARG (0));
952 } else {
953 esilprintf (op, "0x80,%s,&,!,%s,!,|,?{,%s,pc,=,},", ARG (0), ARG (0), ARG (1));
954 }
955 break;
956 case PPC_BC_GT:
957 if (ARG (1)[0] == '\0') {
958 esilprintf (op, "0x80,cr0,&,!,?{,%s,pc,=,},", ARG (0));
959 } else {
960 esilprintf (op, "0x80,%s,&,!,?{,%s,pc,=,},", ARG (0), ARG (1));
961 }
962 break;
963 case PPC_BC_NE:
964 if (ARG (1)[0] == '\0') {
965 esilprintf (op, "cr0,!,!,?{,%s,pc,=,},", ARG (0));
966 } else {
967 esilprintf (op, "%s,!,!,?{,%s,pc,=,},", ARG (0), ARG (1));
968 }
969 break;
970 case PPC_BC_INVALID:
971 op->type = R_ANAL_OP_TYPE_JMP;
972 esilprintf (op, "%s,pc,=", ARG (0));
973 case PPC_BC_UN: // unordered
974 case PPC_BC_NU: // not unordered
975 case PPC_BC_SO: // summary overflow
976 case PPC_BC_NS: // not summary overflow
977 default:
978 break;
979 }
980 break;
981 case PPC_INS_BT:
982 case PPC_INS_BF:
983 switch (insn->detail->ppc.operands[0].type) {
984 case PPC_OP_CRX:
985 op->type = R_ANAL_OP_TYPE_CJMP;
986 op->fail = addr + op->size;
987 break;
988 case PPC_OP_REG:
989 if (op->type == R_ANAL_OP_TYPE_CJMP) {
990 op->type = R_ANAL_OP_TYPE_UCJMP;
991 } else {
992 op->type = R_ANAL_OP_TYPE_CJMP;
993 }
994 op->jump = IMM (1);
995 op->fail = addr + op->size;
996 //op->type = R_ANAL_OP_TYPE_UJMP;
997 default:
998 break;
999 }
1000 break;
1001 case PPC_INS_BDNZ:
1002 op->type = R_ANAL_OP_TYPE_CJMP;
1003 op->jump = IMM (0);
1004 op->fail = addr + op->size;
1005 esilprintf (op, "1,ctr,-=,$z,!,?{,%s,pc,=,}", ARG (0));
1006 break;
1007 case PPC_INS_BDNZA:
1008 op->type = R_ANAL_OP_TYPE_CJMP;
1009 op->jump = IMM (0);
1010 op->fail = addr + op->size;
1011 break;
1012 case PPC_INS_BDNZL:
1013 op->type = R_ANAL_OP_TYPE_CJMP;
1014 op->jump = IMM (0);
1015 op->fail = addr + op->size;
1016 break;
1017 case PPC_INS_BDNZLA:
1018 op->type = R_ANAL_OP_TYPE_CJMP;
1019 op->jump = IMM (0);
1020 op->fail = addr + op->size;
1021 break;
1022 case PPC_INS_BDNZLR:
1023 op->type = R_ANAL_OP_TYPE_CJMP;
1024 op->fail = addr + op->size;
1025 esilprintf (op, "1,ctr,-=,$z,!,?{,lr,pc,=,},");
1026 break;
1027 case PPC_INS_BDNZLRL:
1028 op->fail = addr + op->size;
1029 op->type = R_ANAL_OP_TYPE_CJMP;
1030 break;
1031 case PPC_INS_BDZ:
1032 op->type = R_ANAL_OP_TYPE_CJMP;
1033 op->jump = IMM (0);
1034 op->fail = addr + op->size;
1035 esilprintf (op, "1,ctr,-=,$z,?{,%s,pc,=,}", ARG (0));
1036 break;
1037 case PPC_INS_BDZA:
1038 op->type = R_ANAL_OP_TYPE_CJMP;
1039 op->jump = IMM (0);
1040 op->fail = addr + op->size;
1041 break;
1042 case PPC_INS_BDZL:
1043 op->type = R_ANAL_OP_TYPE_CJMP;
1044 op->jump = IMM (0);
1045 op->fail = addr + op->size;
1046 break;
1047 case PPC_INS_BDZLA:
1048 op->type = R_ANAL_OP_TYPE_CJMP;
1049 op->jump = IMM (0);
1050 op->fail = addr + op->size;
1051 break;
1052 case PPC_INS_BDZLR:
1053 op->type = R_ANAL_OP_TYPE_CJMP;
1054 op->fail = addr + op->size;
1055 esilprintf (op, "1,ctr,-=,$z,?{,lr,pc,=,}");
1056 break;
1057 case PPC_INS_BDZLRL:
1058 op->type = R_ANAL_OP_TYPE_CJMP;
1059 op->fail = addr + op->size;
1060 break;
1061 case PPC_INS_BLR:
1062 case PPC_INS_BLRL:
1063 case PPC_INS_BCLR:
1064 case PPC_INS_BCLRL:
1065 op->type = R_ANAL_OP_TYPE_CRET; //I'm a condret
1066 op->fail = addr + op->size;
1067 switch (insn->detail->ppc.bc) {
1068 case PPC_BC_INVALID:
1069 op->type = R_ANAL_OP_TYPE_RET;
1070 esilprintf (op, "lr,pc,=");
1071 break;
1072 case PPC_BC_LT:
1073 if (ARG (1)[0] == '\0') {
1074 esilprintf (op, "0x80,cr0,&,!,!,?{,lr,pc,=,},");
1075 } else {
1076 esilprintf (op, "0x80,%s,&,!,!,?{,lr,pc,=,},", ARG (0));
1077 }
1078 break;
1079 case PPC_BC_LE:
1080 if (ARG (1)[0] == '\0') {
1081 esilprintf (op, "0x80,cr0,&,!,!,cr0,!,|,?{,lr,pc,=,},");
1082 } else {
1083 esilprintf (op, "0x80,%s,&,!,!,0,%s,!,|,?{,lr,pc,=,},", ARG (0), ARG (0));
1084 }
1085 break;
1086 case PPC_BC_EQ:
1087 if (ARG (1)[0] == '\0') {
1088 esilprintf (op, "cr0,!,?{,lr,pc,=,},");
1089 } else {
1090 esilprintf (op, "%s,!,?{,lr,pc,=,},", ARG (0));
1091 }
1092 break;
1093 case PPC_BC_GE:
1094 if (ARG (1)[0] == '\0') {
1095 esilprintf (op, "0x80,cr0,&,!,cr0,!,|,?{,lr,pc,=,},");
1096 } else {
1097 esilprintf (op, "0x80,%s,&,!,%s,!,|,?{,lr,pc,=,},", ARG (0), ARG (0));
1098 }
1099 break;
1100 case PPC_BC_GT:
1101 if (ARG (1)[0] == '\0') {
1102 esilprintf (op, "0x80,cr0,&,!,?{,lr,pc,=,},");
1103 } else {
1104 esilprintf (op, "0x80,%s,&,!,?{,lr,pc,=,},", ARG (0));
1105 }
1106 break;
1107 case PPC_BC_NE:
1108 if (ARG (1)[0] == '\0') {
1109 esilprintf (op, "cr0,!,!,?{,lr,pc,=,},");
1110 } else {
1111 esilprintf (op, "%s,!,!,?{,lr,pc,=,},", ARG (0));
1112 }
1113 break;
1114 case PPC_BC_UN: // unordered
1115 case PPC_BC_NU: // not unordered
1116 case PPC_BC_SO: // summary overflow
1117 case PPC_BC_NS: // not summary overflow
1118 default:
1119 break;
1120 }
1121 break;
1122 case PPC_INS_NOR:
1123 op->type = R_ANAL_OP_TYPE_NOR;
1124 esilprintf (op, "%s,%s,|,!,%s,=", ARG (2), ARG (1), ARG (0));
1125 break;
1126 case PPC_INS_XOR:
1127 case PPC_INS_XORI:
1128 op->type = R_ANAL_OP_TYPE_XOR;
1129 esilprintf (op, "%s,%s,^,%s,=", ARG (2), ARG (1), ARG (0));
1130 break;
1131 case PPC_INS_XORIS:
1132 op->type = R_ANAL_OP_TYPE_XOR;
1133 esilprintf (op, "16,%s,<<,%s,^,%s,=", ARG (2), ARG (1), ARG (0));
1134 break;
1135 case PPC_INS_DIVD:
1136 case PPC_INS_DIVW:
1137 op->sign = true;
1138 op->type = R_ANAL_OP_TYPE_DIV;
1139 esilprintf (op, "%s,%s,/,%s,=", ARG (2), ARG (1), ARG (0));
1140 break;
1141 case PPC_INS_DIVDU:
1142 case PPC_INS_DIVWU:
1143 op->type = R_ANAL_OP_TYPE_DIV;
1144 esilprintf (op, "%s,%s,/,%s,=", ARG (2), ARG (1), ARG (0));
1145 break;
1146 case PPC_INS_BL:
1147 case PPC_INS_BLA:
1148 op->type = R_ANAL_OP_TYPE_CALL;
1149 op->jump = IMM (0);
1150 op->fail = addr + op->size;
1151 esilprintf (op, "pc,lr,=,%s,pc,=", ARG (0));
1152 break;
1153 case PPC_INS_TRAP:
1154 op->sign = true;
1155 op->type = R_ANAL_OP_TYPE_TRAP;
1156 break;
1157 case PPC_INS_AND:
1158 case PPC_INS_NAND:
1159 case PPC_INS_ANDI:
1160 op->type = R_ANAL_OP_TYPE_AND;
1161 esilprintf (op, "%s,%s,&,%s,=", ARG (2), ARG (1), ARG (0));
1162 break;
1163 case PPC_INS_ANDIS:
1164 op->type = R_ANAL_OP_TYPE_AND;
1165 esilprintf (op, "16,%s,<<,%s,&,%s,=", ARG (2), ARG (1), ARG (0));
1166 break;
1167 case PPC_INS_OR:
1168 case PPC_INS_ORI:
1169 op->type = R_ANAL_OP_TYPE_OR;
1170 esilprintf (op, "%s,%s,|,%s,=", ARG (2), ARG (1), ARG (0));
1171 break;
1172 case PPC_INS_ORIS:
1173 op->type = R_ANAL_OP_TYPE_OR;
1174 esilprintf (op, "16,%s,<<,%s,|,%s,=", ARG (2), ARG (1), ARG (0));
1175 break;
1176 case PPC_INS_MFPVR:
1177 op->type = R_ANAL_OP_TYPE_MOV;
1178 esilprintf (op, "pvr,%s,=", ARG (0));
1179 break;
1180 case PPC_INS_MFSPR:
1181 op->type = R_ANAL_OP_TYPE_MOV;
1182 esilprintf (op, "%s,%s,=", PPCSPR (1), ARG (0));
1183 break;
1184 case PPC_INS_MFCTR:
1185 op->type = R_ANAL_OP_TYPE_MOV;
1186 esilprintf (op, "ctr,%s,=", ARG (0));
1187 break;
1188 case PPC_INS_MFDCCR:
1189 op->type = R_ANAL_OP_TYPE_MOV;
1190 esilprintf (op, "dccr,%s,=", ARG (0));
1191 break;
1192 case PPC_INS_MFICCR:
1193 op->type = R_ANAL_OP_TYPE_MOV;
1194 esilprintf (op, "iccr,%s,=", ARG (0));
1195 break;
1196 case PPC_INS_MFDEAR:
1197 op->type = R_ANAL_OP_TYPE_MOV;
1198 esilprintf (op, "dear,%s,=", ARG (0));
1199 break;
1200 case PPC_INS_MFMSR:
1201 op->type = R_ANAL_OP_TYPE_MOV;
1202 esilprintf (op, "msr,%s,=", ARG (0));
1203 break;
1204 case PPC_INS_MTCTR:
1205 op->type = R_ANAL_OP_TYPE_MOV;
1206 esilprintf (op, "%s,ctr,=", ARG (0));
1207 break;
1208 case PPC_INS_MTDCCR:
1209 op->type = R_ANAL_OP_TYPE_MOV;
1210 esilprintf (op, "%s,dccr,=", ARG (0));
1211 break;
1212 case PPC_INS_MTICCR:
1213 op->type = R_ANAL_OP_TYPE_MOV;
1214 esilprintf (op, "%s,iccr,=", ARG (0));
1215 break;
1216 case PPC_INS_MTDEAR:
1217 op->type = R_ANAL_OP_TYPE_MOV;
1218 esilprintf (op, "%s,dear,=", ARG (0));
1219 break;
1220 case PPC_INS_MTMSR:
1221 case PPC_INS_MTMSRD:
1222 op->type = R_ANAL_OP_TYPE_MOV;
1223 esilprintf (op, "%s,msr,=", ARG (0));
1224 break;
1225 // Data Cache Block Zero
1226 case PPC_INS_DCBZ:
1227 op->type = R_ANAL_OP_TYPE_STORE;
1228 esilprintf (op, "%s,%s", ARG (0), ARG2 (1, ",=[128]"));
1229 break;
1230 case PPC_INS_CLRLDI:
1231 op->type = R_ANAL_OP_TYPE_AND;
1232 esilprintf (op, "%s,%s,&,%s,=", ARG (1), cmask64 (ARG (2), "0x3F"), ARG (0));
1233 break;
1234 case PPC_INS_ROTLDI:
1235 op->type = R_ANAL_OP_TYPE_ROL;
1236 esilprintf (op, "%s,%s,<<<,%s,=", ARG (2), ARG (1), ARG (0));
1237 break;
1238 case PPC_INS_RLDCL:
1239 case PPC_INS_RLDICL:
1240 op->type = R_ANAL_OP_TYPE_ROL;
1241 esilprintf (op, "%s,%s,<<<,%s,&,%s,=", ARG (2), ARG (1), cmask64 (ARG (3), "0x3F"), ARG (0));
1242 break;
1243 case PPC_INS_RLDCR:
1244 case PPC_INS_RLDICR:
1245 op->type = R_ANAL_OP_TYPE_ROL;
1246 esilprintf (op, "%s,%s,<<<,%s,&,%s,=", ARG (2), ARG (1), cmask64 (0, ARG (3)), ARG (0));
1247 break;
1248 }
1249 if (mask & R_ANAL_OP_MASK_VAL) {
1250 op_fillval (op, handle, insn);
1251 }
1252 if (!(mask & R_ANAL_OP_MASK_ESIL)) {
1253 r_strbuf_fini (&op->esil);
1254 }
1255 cs_free (insn, n);
1256 //cs_close (&handle);
1257 }
1258 return op->size;
1259 }
1260
archinfo(RAnal * a,int q)1261 static int archinfo(RAnal *a, int q) {
1262 if (a->cpu && !strncmp (a->cpu, "vle", 3)) {
1263 return 2;
1264 }
1265 return 4;
1266 }
1267
anal_preludes(RAnal * anal)1268 static RList *anal_preludes(RAnal *anal) {
1269 #define KW(d,ds,m,ms) r_list_append (l, r_search_keyword_new((const ut8*)d,ds,(const ut8*)m, ms, NULL))
1270 RList *l = r_list_newf ((RListFree)r_search_keyword_free);
1271 KW ("\x7c\x08\x02\xa6", 4, NULL, 0);
1272 return l;
1273 }
1274
1275 RAnalPlugin r_anal_plugin_ppc_cs = {
1276 .name = "ppc",
1277 .desc = "Capstone PowerPC analysis",
1278 .license = "BSD",
1279 .esil = true,
1280 .arch = "ppc",
1281 .bits = 32 | 64,
1282 .archinfo = archinfo,
1283 .preludes = anal_preludes,
1284 .op = &analop,
1285 .set_reg_profile = &set_reg_profile,
1286 };
1287
1288 #ifndef R2_PLUGIN_INCORE
1289 R_API RLibStruct radare_plugin = {
1290 .type = R_LIB_TYPE_ANAL,
1291 .data = &r_anal_plugin_ppc_cs,
1292 .version = R2_VERSION
1293 };
1294 #endif
1295