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