rizin/librz/arch/p/analysis/analysis_ppc_cs.c
Khairul Azhar Kasmiran c8878d3139
Convert %ll format specifiers to PFMT64 (#6267)
* Convert `%ll` format specifiers to PFMT64
* Remove ` ""` at end of some PFMT64
2026-04-22 05:57:04 +08:00

1818 lines
52 KiB
C

// SPDX-FileCopyrightText: 2013-2019 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_analysis.h>
#include <rz_lib.h>
#include <capstone/capstone.h>
#include <capstone/ppc.h>
#include "ppc/libvle/vle.h"
#include "ppc/ppc_analysis.h"
#include "ppc/ppc_il.h"
#include "rz_util/rz_strbuf.h"
#define SPR_HID0 0x3f0 /* Hardware Implementation Register 0 */
#define SPR_HID1 0x3f1 /* Hardware Implementation Register 1 */
#define SPR_HID2 0x3f3 /* Hardware Implementation Register 2 */
#define SPR_HID4 0x3f4 /* Hardware Implementation Register 4 */
#define SPR_HID5 0x3f6 /* Hardware Implementation Register 5 */
#define SPR_HID6 0x3f9 /* Hardware Implementation Register 6 */
struct Getarg {
csh handle;
cs_insn *insn;
int bits;
};
#ifndef PFMT32x
#define PFMT32x "lx"
#endif
static ut64 mask64(ut64 mb, ut64 me) {
ut64 maskmb = UT64_MAX >> mb;
ut64 maskme = UT64_MAX << (63 - me);
return (mb <= me) ? maskmb & maskme : maskmb | maskme;
}
static ut32 mask32(ut32 mb, ut32 me) {
ut32 maskmb = UT32_MAX >> mb;
ut32 maskme = UT32_MAX << (31 - me);
return (mb <= me) ? maskmb & maskme : maskmb | maskme;
}
typedef struct {
char cmask1[32];
char cmask2[32];
char words[8][64];
char cspr[16];
csh handle;
int omode;
int obits;
RzRegItem base_regs[4];
} PPCContext;
static bool ppc_init(void **user) {
PPCContext *ctx = RZ_NEW0(PPCContext);
if (!ctx) {
return false;
}
ctx->handle = 0;
ctx->omode = -1;
ctx->obits = -1;
*user = ctx;
return true;
}
static const char *cmask64(RzAnalysis *a, const char *mb_c, const char *me_c) {
PPCContext *ctx = (PPCContext *)a->plugin_data;
ut64 mb = 0;
ut64 me = 0;
if (mb_c) {
mb = strtol(mb_c, NULL, 16);
}
if (me_c) {
me = strtol(me_c, NULL, 16);
}
snprintf(ctx->cmask1, sizeof(ctx->cmask1), "0x%" PFMT64x, mask64(mb, me));
return ctx->cmask1;
}
static const char *cmask32(RzAnalysis *a, const char *mb_c, const char *me_c) {
PPCContext *ctx = (PPCContext *)a->plugin_data;
ut32 mb = 0;
ut32 me = 0;
if (mb_c) {
mb = strtol(mb_c, NULL, 16);
}
if (me_c) {
me = strtol(me_c, NULL, 16);
}
snprintf(ctx->cmask2, sizeof(ctx->cmask2), "0x%" PFMT32x "", mask32(mb, me));
return ctx->cmask2;
}
static char *getarg2(RzAnalysis *a, struct Getarg *gop, int n, const char *setstr) {
PPCContext *ctx = (PPCContext *)a->plugin_data;
cs_insn *insn = gop->insn;
csh handle = gop->handle;
cs_ppc_op op;
if (n < 0 || n >= 8) {
return NULL;
}
op = INSOP(n);
switch (op.type) {
case PPC_OP_INVALID:
ctx->words[n][0] = '\0';
// strcpy (words[n], "invalid");
break;
case PPC_OP_REG:
snprintf(ctx->words[n], sizeof(ctx->words[n]),
"%s%s", cs_reg_name(handle, op.reg), setstr);
break;
case PPC_OP_IMM:
snprintf(ctx->words[n], sizeof(ctx->words[n]),
"0x%" PFMT64x "%s", (ut64)op.imm, setstr);
break;
case PPC_OP_MEM:
snprintf(ctx->words[n], sizeof(ctx->words[n]),
"%" PFMT64d ",%s,+,%s",
(ut64)op.mem.disp,
cs_reg_name(handle, op.mem.base), setstr);
break;
#if CS_NEXT_VERSION < 6
case PPC_OP_CRX: // Condition Register field
snprintf(ctx->words[n], sizeof(ctx->words[n]),
"%" PFMT64d "%s", (ut64)op.imm, setstr);
break;
#endif
}
return ctx->words[n];
}
static ut64 getarg(struct Getarg *gop, int n) {
ut64 value = 0;
cs_insn *insn = gop->insn;
cs_ppc_op op;
if (n < 0 || n >= 8) {
return 0;
}
op = INSOP(n);
switch (op.type) {
case PPC_OP_INVALID:
break;
case PPC_OP_REG:
value = op.reg;
break;
case PPC_OP_IMM:
value = (ut64)op.imm;
break;
case PPC_OP_MEM:
value = op.mem.disp + op.mem.base;
break;
#if CS_NEXT_VERSION < 6
case PPC_OP_CRX: // Condition Register field
value = (ut64)op.imm;
break;
#endif
}
return value;
}
static const char *getspr(RzAnalysis *a, struct Getarg *gop, int n) {
PPCContext *ctx = (PPCContext *)a->plugin_data;
ut32 spr = 0;
if (n < 0 || n >= 8) {
return NULL;
}
spr = getarg(gop, 0);
switch (spr) {
case SPR_HID0:
return "hid0";
case SPR_HID1:
return "hid1";
case SPR_HID2:
return "hid2";
case SPR_HID4:
return "hid4";
case SPR_HID5:
return "hid5";
case SPR_HID6:
return "hid6";
default:
snprintf(ctx->cspr, sizeof(ctx->cspr), "spr_%u", spr);
break;
}
return ctx->cspr;
}
static RzStructuredData *ppc_opex(csh handle, cs_insn *insn) {
if (!insn->detail) {
return NULL;
}
RzStructuredData *root = rz_structured_data_new_map();
if (!root) {
return NULL;
}
RzStructuredData *opex = rz_structured_data_map_add_map(root, "opex");
if (!opex) {
rz_structured_data_free(root);
return NULL;
}
RzStructuredData *operands = rz_structured_data_map_add_array(opex, "operands");
cs_ppc *x = &insn->detail->ppc;
for (st32 i = 0; i < x->op_count; i++) {
cs_ppc_op *op = x->operands + i;
RzStructuredData *operand = rz_structured_data_array_add_map(operands);
switch (op->type) {
case PPC_OP_REG:
rz_structured_data_map_add_string(operand, "type", "reg");
rz_structured_data_map_add_string(operand, "value", cs_reg_name(handle, op->reg));
break;
case PPC_OP_IMM:
rz_structured_data_map_add_string(operand, "type", "imm");
rz_structured_data_map_add_signed(operand, "value", op->imm);
break;
case PPC_OP_MEM:
rz_structured_data_map_add_string(operand, "type", "mem");
if (op->mem.base != PPC_REG_INVALID) {
rz_structured_data_map_add_string(operand, "base", cs_reg_name(handle, op->mem.base));
}
rz_structured_data_map_add_signed(operand, "disp", op->mem.disp);
break;
default:
rz_structured_data_map_add_string(operand, "type", "invalid");
break;
}
}
return root;
}
#define PPCSPR(n) getspr(a, &gop, n)
#define ARG(n) getarg2(a, &gop, n, "")
#define ARG2(n, m) getarg2(a, &gop, n, m)
static char *ppc_get_reg_profile(RzAnalysis *analysis) {
const char *p = NULL;
if (analysis->bits == 64) {
p =
"=PC pc\n"
"=SP r1\n"
"=BP r31\n"
"=SN r3\n" // also for ret
"=A0 r3\n" // also for ret
"=A1 r4\n"
"=A2 r5\n"
"=A3 r6\n"
"=A4 r7\n"
"=A5 r8\n"
"=A6 r6\n"
"=OF ov\n"
"=CF ca\n"
"gpr r0 .64 0 0 \n"
"gpr r1 .64 8 0 \n"
"gpr r2 .64 16 0 \n"
"gpr r3 .64 24 0 \n"
"gpr r4 .64 32 0 \n"
"gpr r5 .64 40 0 \n"
"gpr r6 .64 48 0 \n"
"gpr r7 .64 56 0 \n"
"gpr r8 .64 64 0 \n"
"gpr r9 .64 72 0 \n"
"gpr r10 .64 80 0 \n"
"gpr r11 .64 88 0 \n"
"gpr r12 .64 96 0 \n"
"gpr r13 .64 104 0 \n"
"gpr r14 .64 112 0 \n"
"gpr r15 .64 120 0 \n"
"gpr r16 .64 128 0 \n"
"gpr r17 .64 136 0 \n"
"gpr r18 .64 144 0 \n"
"gpr r19 .64 152 0 \n"
"gpr r20 .64 160 0 \n"
"gpr r21 .64 168 0 \n"
"gpr r22 .64 176 0 \n"
"gpr r23 .64 184 0 \n"
"gpr r24 .64 192 0 \n"
"gpr r25 .64 200 0 \n"
"gpr r26 .64 208 0 \n"
"gpr r27 .64 216 0 \n"
"gpr r28 .64 224 0 \n"
"gpr r29 .64 232 0 \n"
"gpr r30 .64 240 0 \n"
"gpr r31 .64 248 0 \n"
"vc vs0 .128 256 0 \n"
"vc vs1 .128 272 0 \n"
"vc vs2 .128 288 0 \n"
"vc vs3 .128 304 0 \n"
"vc vs4 .128 320 0 \n"
"vc vs5 .128 336 0 \n"
"vc vs6 .128 352 0 \n"
"vc vs7 .128 368 0 \n"
"vc vs8 .128 384 0 \n"
"vc vs9 .128 400 0 \n"
"vc vs10 .128 416 0 \n"
"vc vs11 .128 432 0 \n"
"vc vs12 .128 448 0 \n"
"vc vs13 .128 464 0 \n"
"vc vs14 .128 480 0 \n"
"vc vs15 .128 496 0 \n"
"vc vs16 .128 512 0 \n"
"vc vs17 .128 528 0 \n"
"vc vs18 .128 544 0 \n"
"vc vs19 .128 560 0 \n"
"vc vs20 .128 576 0 \n"
"vc vs21 .128 592 0 \n"
"vc vs22 .128 608 0 \n"
"vc vs23 .128 624 0 \n"
"vc vs24 .128 640 0 \n"
"vc vs25 .128 656 0 \n"
"vc vs26 .128 672 0 \n"
"vc vs27 .128 688 0 \n"
"vc vs28 .128 704 0 \n"
"vc vs29 .128 720 0 \n"
"vc vs30 .128 736 0 \n"
"vc vs31 .128 752 0 \n"
"vc vs32 .128 768 0 \n"
"vc vs33 .128 784 0 \n"
"vc vs34 .128 800 0 \n"
"vc vs35 .128 816 0 \n"
"vc vs36 .128 832 0 \n"
"vc vs37 .128 848 0 \n"
"vc vs38 .128 864 0 \n"
"vc vs39 .128 880 0 \n"
"vc vs40 .128 896 0 \n"
"vc vs41 .128 912 0 \n"
"vc vs42 .128 928 0 \n"
"vc vs43 .128 944 0 \n"
"vc vs44 .128 960 0 \n"
"vc vs45 .128 976 0 \n"
"vc vs46 .128 992 0 \n"
"vc vs47 .128 1008 0 \n"
"vc vs48 .128 1024 0 \n"
"vc vs49 .128 1040 0 \n"
"vc vs50 .128 1056 0 \n"
"vc vs51 .128 1072 0 \n"
"vc vs52 .128 1088 0 \n"
"vc vs53 .128 1104 0 \n"
"vc vs54 .128 1120 0 \n"
"vc vs55 .128 1136 0 \n"
"vc vs56 .128 1152 0 \n"
"vc vs57 .128 1168 0 \n"
"vc vs58 .128 1184 0 \n"
"vc vs59 .128 1200 0 \n"
"vc vs60 .128 1216 0 \n"
"vc vs61 .128 1232 0 \n"
"vc vs62 .128 1248 0 \n"
"vc vs63 .128 1264 0 \n"
"fpu f0 .64 1280 0 \n"
"fpu f1 .64 1288 0 \n"
"fpu f2 .64 1296 0 \n"
"fpu f3 .64 1304 0 \n"
"fpu f4 .64 1312 0 \n"
"fpu f5 .64 1320 0 \n"
"fpu f6 .64 1328 0 \n"
"fpu f7 .64 1336 0 \n"
"fpu f8 .64 1344 0 \n"
"fpu f9 .64 1352 0 \n"
"fpu f10 .64 1360 0 \n"
"fpu f11 .64 1368 0 \n"
"fpu f12 .64 1376 0 \n"
"fpu f13 .64 1384 0 \n"
"fpu f14 .64 1392 0 \n"
"fpu f15 .64 1400 0 \n"
"fpu f16 .64 1408 0 \n"
"fpu f17 .64 1416 0 \n"
"fpu f18 .64 1424 0 \n"
"fpu f19 .64 1432 0 \n"
"fpu f20 .64 1440 0 \n"
"fpu f21 .64 1448 0 \n"
"fpu f22 .64 1456 0 \n"
"fpu f23 .64 1464 0 \n"
"fpu f24 .64 1472 0 \n"
"fpu f25 .64 1480 0 \n"
"fpu f26 .64 1488 0 \n"
"fpu f27 .64 1496 0 \n"
"fpu f28 .64 1504 0 \n"
"fpu f29 .64 1512 0 \n"
"fpu f30 .64 1520 0 \n"
"fpu f31 .64 1528 0 \n"
"vc v0 .128 1536 0 \n"
"vc v1 .128 1552 0 \n"
"vc v2 .128 1568 0 \n"
"vc v3 .128 1584 0 \n"
"vc v4 .128 1600 0 \n"
"vc v5 .128 1616 0 \n"
"vc v6 .128 1632 0 \n"
"vc v7 .128 1648 0 \n"
"vc v8 .128 1664 0 \n"
"vc v9 .128 1680 0 \n"
"vc v10 .128 1696 0 \n"
"vc v11 .128 1712 0 \n"
"vc v12 .128 1728 0 \n"
"vc v13 .128 1744 0 \n"
"vc v14 .128 1760 0 \n"
"vc v15 .128 1776 0 \n"
"vc v16 .128 1792 0 \n"
"vc v17 .128 1808 0 \n"
"vc v18 .128 1824 0 \n"
"vc v19 .128 1840 0 \n"
"vc v20 .128 1856 0 \n"
"vc v21 .128 1872 0 \n"
"vc v22 .128 1888 0 \n"
"vc v23 .128 1904 0 \n"
"vc v24 .128 1920 0 \n"
"vc v25 .128 1936 0 \n"
"vc v26 .128 1952 0 \n"
"vc v27 .128 1968 0 \n"
"vc v28 .128 1984 0 \n"
"vc v29 .128 2000 0 \n"
"vc v30 .128 2016 0 \n"
"vc v31 .128 2032 0 \n"
"ctr xer .64 2048 0 # Fixed-Point Exception Register\n"
"vcc vrsave .32 2056 0 # VR Save Register\n"
"ctr fpscr .64 2060 0 # Floating-Point Status and Control Register\n"
"vcc vscr .32 2068 0 # Vector Status and Control Register\n"
"ctr cr .32 2072 0 # Condition Register\n"
"ctr lr .64 2076 0 # Link Register\n"
"ctr ctr .64 2084 0 # Count Register\n"
"ctr tar .64 2092 0 # Target Address Register\n"
"ctr ppr .64 2100 0 # Process Priority Register\n"
"ctr dscr .64 2108 0 # Data Stream Control Register\n"
"ctr bescr .64 2116 0 # Branch Event Status and Control Register\n"
"ctr ebbhr .64 2124 0 # Event-Based Branch Handler Register\n"
"ctr ebbrr .64 2132 0 # Event-Based Branch Return Register\n"
"ctr lpcr .64 2140 0 # Logical Partitioning Control Register\n"
"ctr hrmor .64 2148 0 # Hypervisor Real Mode Offset Register\n"
"ctr lpidr .32 2156 0 # Logical Partition Identification Regiser\n"
"ctr pcr .64 2160 0 # Processor Compatibility Register\n"
"ctr tir .64 2168 0 # Thread Identification Register\n"
"ctr urmor .64 2176 0 # Ultravisor Real Mode Offset Register\n"
"ctr smfctrl .64 2184 0 # Secure Memory Facility Control Register\n"
"ctr msr .64 2192 0 # Machine State Register\n"
"ctr pvr .32 2200 0 # Processor Version Register\n"
"ctr pir .32 2204 0 # Processor Version Register\n"
"ctr pidr .32 2208 0 # Processor Identification Register\n"
"ctr ctrl .32 2212 0 # Control Register\n"
"ctr pspb .32 2216 0 # Problem State Priority Boost Register\n"
"ctr rpr .64 2220 0 # Relative Priority Register\n"
"ctr hashkey .64 2228 0 # Hash Key Register\n"
"ctr hashpkey .64 2236 0 # Hash Privileged Key Register\n"
"ctr sprg0 .64 2244 0 # Software-use SPR 0\n"
"ctr sprg1 .64 2252 0 # Software-use SPR 1\n"
"ctr sprg2 .64 2260 0 # Software-use SPR 2\n"
"ctr sprg3 .64 2268 0 # Software-use SPR 3\n"
"ctr hsprg0 .64 2276 0 # Hypervisor Software-use SPR 0\n"
"ctr hsprg1 .64 2284 0 # Hypervisor Software-use SPR 1\n"
"ctr usprg0 .64 2292 0 # Ultravisor Software-use SPR 0\n"
"ctr usprg1 .64 2300 0 # Ultravisor Software-use SPR 1\n"
"ctr srr0 .64 2308 0 # Machine Status Save/Restore Register 0\n"
"ctr srr1 .64 2316 0 # Machine Status Save/Restore Register 1\n"
"ctr hsrr0 .64 2324 0 # Hypervisor Machine Status Save/Restore Register 0\n"
"ctr hsrr1 .64 2332 0 # Hypervisor Machine Status Save/Restore Register 1\n"
"ctr usrr0 .64 2340 0 # Hypervisor Machine Status Save/Restore Register 0\n"
"ctr usrr1 .64 2348 0 # Ultravisor Machine Status Save/Restore Register 1\n"
"ctr asdr .64 2356 0 # Access Segment Descriptor Register\n"
"ctr dar .64 2364 0 # Data Address Register\n"
"ctr hdar .64 2372 0 # Hypervisor Data Address Register\n"
"ctr dsisr .32 2380 0 # Data Storage Interrupt Status Register\n"
"ctr hdsisr .32 2384 0 # Hypervisor Data Storage Interrupt Status Register\n"
"ctr heir .64 2388 0 # Hypervisor Emulation Instruction Register\n"
"ctr hmer .64 2396 0 # Hypervisor Maintenance Exception Register\n"
"ctr hmeer .64 2404 0 # Hypervisor Maintenance Exception Enable Register\n"
"ctr fscr .64 2412 0 # Facility Status and Control Register\n"
"ctr hfscr .64 2420 0 # Hypervisor Facility Status and Control Register\n"
"ctr purr .64 2428 0 # Process Utilization of Resources Register\n"
"ctr spurr .64 2436 0 # Scaled Process Utilization of Resources Register\n"
"ctr dexcr .64 2444 0 # Dynamic Execution Control Register\n"
"ctr hdexcr .64 2452 0 # Hypervisor Dynamic Execution Control Register\n"
"ctr udexcr .64 2460 0 # Ultravisor Dynamic Execution Control Register\n"
"ctr cfar .64 2468 0 # Come-From Address Register\n"
"ctr mmcr0 .64 2476 0 # Monitor Mode Control Register 0\n"
"ctr mmcr1 .64 2484 0 # Monitor Mode Control Register 1\n"
"ctr mmcr2 .64 2492 0 # Monitor Mode Control Register 2\n"
"ctr mmcra .64 2500 0 # Monitor Mode Control Register A\n"
"ctr siar .64 2508 0 # Sampled Instruction Address Register\n"
"ctr sdar .64 2516 0 # Sampled Data Address Register\n"
"ctr sier .64 2524 0 # Sampled Instruction Event Register\n"
"ctr sier2 .64 2532 0 # Sampled Instruction Event Register 2\n"
"ctr sier3 .64 2540 0 # Sampled Instruction Event Register 3\n"
"ctr mmcr3 .64 2548 0 # Monitor Mode Control Register 2\n"
"ctr dpdes .64 2556 0 # Directed Privileged Doorbell Exception State Register\n"
"ctr pc .64 2564 0 # Programm Counter\n"
"ctr cr0 .4 2572 0 # Condition Register Field 0\n"
"ctr cr1 .4 2573 0 # Condition Register Field 1\n"
"ctr cr2 .4 2574 0 # Condition Register Field 2\n"
"ctr cr3 .4 2575 0 # Condition Register Field 3\n"
"ctr cr4 .4 2576 0 # Condition Register Field 4\n"
"ctr cr5 .4 2577 0 # Condition Register Field 5\n"
"ctr cr6 .4 2578 0 # Condition Register Field 6\n"
"ctr cr7 .4 2579 0 # Condition Register Field 7\n"
"ctr ppr32 .32 2580 0 # Process Priority Register 32-bit\n"
"flg so .1 2584 0 # Summary Overflow\n"
"flg ov .1 2585 0 # Overflow\n"
"flg ca .1 2586 0 # Carry\n"
"gpr 0 .64 2587 0 # The zero register.\n";
return rz_str_dup(p);
} else {
p =
"=PC pc\n"
"=SP r1\n"
"=BP r31\n"
"=SN r3\n" // also for ret
"=A0 r3\n" // also for ret
"=A1 r4\n"
"=A2 r5\n"
"=A3 r6\n"
"=A4 r7\n"
"=A5 r8\n"
"=A6 r6\n"
"=OF ov\n"
"=CF ca\n"
"gpr r0 .32 0 0 \n"
"gpr r1 .32 8 0 \n"
"gpr r2 .32 16 0 \n"
"gpr r3 .32 24 0 \n"
"gpr r4 .32 32 0 \n"
"gpr r5 .32 40 0 \n"
"gpr r6 .32 48 0 \n"
"gpr r7 .32 56 0 \n"
"gpr r8 .32 64 0 \n"
"gpr r9 .32 72 0 \n"
"gpr r10 .32 80 0 \n"
"gpr r11 .32 88 0 \n"
"gpr r12 .32 96 0 \n"
"gpr r13 .32 104 0 \n"
"gpr r14 .32 112 0 \n"
"gpr r15 .32 120 0 \n"
"gpr r16 .32 128 0 \n"
"gpr r17 .32 136 0 \n"
"gpr r18 .32 144 0 \n"
"gpr r19 .32 152 0 \n"
"gpr r20 .32 160 0 \n"
"gpr r21 .32 168 0 \n"
"gpr r22 .32 176 0 \n"
"gpr r23 .32 184 0 \n"
"gpr r24 .32 192 0 \n"
"gpr r25 .32 200 0 \n"
"gpr r26 .32 208 0 \n"
"gpr r27 .32 216 0 \n"
"gpr r28 .32 224 0 \n"
"gpr r29 .32 232 0 \n"
"gpr r30 .32 240 0 \n"
"gpr r31 .32 248 0 \n"
"vc vs0 .128 256 0 \n"
"vc vs1 .128 272 0 \n"
"vc vs2 .128 288 0 \n"
"vc vs3 .128 304 0 \n"
"vc vs4 .128 320 0 \n"
"vc vs5 .128 336 0 \n"
"vc vs6 .128 352 0 \n"
"vc vs7 .128 368 0 \n"
"vc vs8 .128 384 0 \n"
"vc vs9 .128 400 0 \n"
"vc vs10 .128 416 0 \n"
"vc vs11 .128 432 0 \n"
"vc vs12 .128 448 0 \n"
"vc vs13 .128 464 0 \n"
"vc vs14 .128 480 0 \n"
"vc vs15 .128 496 0 \n"
"vc vs16 .128 512 0 \n"
"vc vs17 .128 528 0 \n"
"vc vs18 .128 544 0 \n"
"vc vs19 .128 560 0 \n"
"vc vs20 .128 576 0 \n"
"vc vs21 .128 592 0 \n"
"vc vs22 .128 608 0 \n"
"vc vs23 .128 624 0 \n"
"vc vs24 .128 640 0 \n"
"vc vs25 .128 656 0 \n"
"vc vs26 .128 672 0 \n"
"vc vs27 .128 688 0 \n"
"vc vs28 .128 704 0 \n"
"vc vs29 .128 720 0 \n"
"vc vs30 .128 736 0 \n"
"vc vs31 .128 752 0 \n"
"vc vs32 .128 768 0 \n"
"vc vs33 .128 784 0 \n"
"vc vs34 .128 800 0 \n"
"vc vs35 .128 816 0 \n"
"vc vs36 .128 832 0 \n"
"vc vs37 .128 848 0 \n"
"vc vs38 .128 864 0 \n"
"vc vs39 .128 880 0 \n"
"vc vs40 .128 896 0 \n"
"vc vs41 .128 912 0 \n"
"vc vs42 .128 928 0 \n"
"vc vs43 .128 944 0 \n"
"vc vs44 .128 960 0 \n"
"vc vs45 .128 976 0 \n"
"vc vs46 .128 992 0 \n"
"vc vs47 .128 1008 0 \n"
"vc vs48 .128 1024 0 \n"
"vc vs49 .128 1040 0 \n"
"vc vs50 .128 1056 0 \n"
"vc vs51 .128 1072 0 \n"
"vc vs52 .128 1088 0 \n"
"vc vs53 .128 1104 0 \n"
"vc vs54 .128 1120 0 \n"
"vc vs55 .128 1136 0 \n"
"vc vs56 .128 1152 0 \n"
"vc vs57 .128 1168 0 \n"
"vc vs58 .128 1184 0 \n"
"vc vs59 .128 1200 0 \n"
"vc vs60 .128 1216 0 \n"
"vc vs61 .128 1232 0 \n"
"vc vs62 .128 1248 0 \n"
"vc vs63 .128 1264 0 \n"
"fpu f0 .64 1280 0 \n"
"fpu f1 .64 1288 0 \n"
"fpu f2 .64 1296 0 \n"
"fpu f3 .64 1304 0 \n"
"fpu f4 .64 1312 0 \n"
"fpu f5 .64 1320 0 \n"
"fpu f6 .64 1328 0 \n"
"fpu f7 .64 1336 0 \n"
"fpu f8 .64 1344 0 \n"
"fpu f9 .64 1352 0 \n"
"fpu f10 .64 1360 0 \n"
"fpu f11 .64 1368 0 \n"
"fpu f12 .64 1376 0 \n"
"fpu f13 .64 1384 0 \n"
"fpu f14 .64 1392 0 \n"
"fpu f15 .64 1400 0 \n"
"fpu f16 .64 1408 0 \n"
"fpu f17 .64 1416 0 \n"
"fpu f18 .64 1424 0 \n"
"fpu f19 .64 1432 0 \n"
"fpu f20 .64 1440 0 \n"
"fpu f21 .64 1448 0 \n"
"fpu f22 .64 1456 0 \n"
"fpu f23 .64 1464 0 \n"
"fpu f24 .64 1472 0 \n"
"fpu f25 .64 1480 0 \n"
"fpu f26 .64 1488 0 \n"
"fpu f27 .64 1496 0 \n"
"fpu f28 .64 1504 0 \n"
"fpu f29 .64 1512 0 \n"
"fpu f30 .64 1520 0 \n"
"fpu f31 .64 1528 0 \n"
"vc v0 .128 1536 0 \n"
"vc v1 .128 1552 0 \n"
"vc v2 .128 1568 0 \n"
"vc v3 .128 1584 0 \n"
"vc v4 .128 1600 0 \n"
"vc v5 .128 1616 0 \n"
"vc v6 .128 1632 0 \n"
"vc v7 .128 1648 0 \n"
"vc v8 .128 1664 0 \n"
"vc v9 .128 1680 0 \n"
"vc v10 .128 1696 0 \n"
"vc v11 .128 1712 0 \n"
"vc v12 .128 1728 0 \n"
"vc v13 .128 1744 0 \n"
"vc v14 .128 1760 0 \n"
"vc v15 .128 1776 0 \n"
"vc v16 .128 1792 0 \n"
"vc v17 .128 1808 0 \n"
"vc v18 .128 1824 0 \n"
"vc v19 .128 1840 0 \n"
"vc v20 .128 1856 0 \n"
"vc v21 .128 1872 0 \n"
"vc v22 .128 1888 0 \n"
"vc v23 .128 1904 0 \n"
"vc v24 .128 1920 0 \n"
"vc v25 .128 1936 0 \n"
"vc v26 .128 1952 0 \n"
"vc v27 .128 1968 0 \n"
"vc v28 .128 1984 0 \n"
"vc v29 .128 2000 0 \n"
"vc v30 .128 2016 0 \n"
"vc v31 .128 2032 0 \n"
"ctr xer .64 2048 0 # Fixed-Point Exception Register\n"
"vcc vrsave .32 2056 0 # VR Save Register\n"
"ctr fpscr .64 2060 0 # Floating-Point Status and Control Register\n"
"vcc vscr .32 2068 0 # Vector Status and Control Register\n"
"ctr cr .32 2072 0 # Condition Register\n"
"ctr lr .32 2076 0 # Link Register\n"
"ctr ctr .32 2084 0 # Count Register\n"
"ctr tar .32 2092 0 # Target Address Register\n"
"ctr ppr .64 2100 0 # Process Priority Register\n"
"ctr dscr .64 2108 0 # Data Stream Control Register\n"
"ctr bescr .64 2116 0 # Branch Event Status and Control Register\n"
"ctr ebbhr .64 2124 0 # Event-Based Branch Handler Register\n"
"ctr ebbrr .64 2132 0 # Event-Based Branch Return Register\n"
"ctr lpcr .64 2140 0 # Logical Partitioning Control Register\n"
"ctr hrmor .64 2148 0 # Hypervisor Real Mode Offset Register\n"
"ctr lpidr .32 2156 0 # Logical Partition Identification Regiser\n"
"ctr pcr .64 2160 0 # Processor Compatibility Register\n"
"ctr tir .64 2168 0 # Thread Identification Register\n"
"ctr urmor .64 2176 0 # Ultravisor Real Mode Offset Register\n"
"ctr smfctrl .64 2184 0 # Secure Memory Facility Control Register\n"
"ctr msr .64 2192 0 # Machine State Register\n"
"ctr pvr .32 2200 0 # Processor Version Register\n"
"ctr pir .32 2204 0 # Processor Version Register\n"
"ctr pidr .32 2208 0 # Processor Identification Register\n"
"ctr ctrl .32 2212 0 # Control Register\n"
"ctr pspb .32 2216 0 # Problem State Priority Boost Register\n"
"ctr rpr .64 2220 0 # Relative Priority Register\n"
"ctr hashkey .64 2228 0 # Hash Key Register\n"
"ctr hashpkey .64 2236 0 # Hash Privileged Key Register\n"
"ctr sprg0 .64 2244 0 # Software-use SPR 0\n"
"ctr sprg1 .64 2252 0 # Software-use SPR 1\n"
"ctr sprg2 .64 2260 0 # Software-use SPR 2\n"
"ctr sprg3 .64 2268 0 # Software-use SPR 3\n"
"ctr hsprg0 .64 2276 0 # Hypervisor Software-use SPR 0\n"
"ctr hsprg1 .64 2284 0 # Hypervisor Software-use SPR 1\n"
"ctr usprg0 .64 2292 0 # Ultravisor Software-use SPR 0\n"
"ctr usprg1 .64 2300 0 # Ultravisor Software-use SPR 1\n"
"ctr srr0 .64 2308 0 # Machine Status Save/Restore Register 0\n"
"ctr srr1 .64 2316 0 # Machine Status Save/Restore Register 1\n"
"ctr hsrr0 .64 2324 0 # Hypervisor Machine Status Save/Restore Register 0\n"
"ctr hsrr1 .64 2332 0 # Hypervisor Machine Status Save/Restore Register 1\n"
"ctr usrr0 .64 2340 0 # Hypervisor Machine Status Save/Restore Register 0\n"
"ctr usrr1 .64 2348 0 # Ultravisor Machine Status Save/Restore Register 1\n"
"ctr asdr .64 2356 0 # Access Segment Descriptor Register\n"
"ctr dar .64 2364 0 # Data Address Register\n"
"ctr hdar .64 2372 0 # Hypervisor Data Address Register\n"
"ctr dsisr .32 2380 0 # Data Storage Interrupt Status Register\n"
"ctr hdsisr .32 2384 0 # Hypervisor Data Storage Interrupt Status Register\n"
"ctr heir .64 2388 0 # Hypervisor Emulation Instruction Register\n"
"ctr hmer .64 2396 0 # Hypervisor Maintenance Exception Register\n"
"ctr hmeer .64 2404 0 # Hypervisor Maintenance Exception Enable Register\n"
"ctr fscr .64 2412 0 # Facility Status and Control Register\n"
"ctr hfscr .64 2420 0 # Hypervisor Facility Status and Control Register\n"
"ctr purr .64 2428 0 # Process Utilization of Resources Register\n"
"ctr spurr .64 2436 0 # Scaled Process Utilization of Resources Register\n"
"ctr dexcr .64 2444 0 # Dynamic Execution Control Register\n"
"ctr hdexcr .64 2452 0 # Hypervisor Dynamic Execution Control Register\n"
"ctr udexcr .64 2460 0 # Ultravisor Dynamic Execution Control Register\n"
"ctr cfar .64 2468 0 # Come-From Address Register\n"
"ctr mmcr0 .64 2476 0 # Monitor Mode Control Register 0\n"
"ctr mmcr1 .64 2484 0 # Monitor Mode Control Register 1\n"
"ctr mmcr2 .64 2492 0 # Monitor Mode Control Register 2\n"
"ctr mmcra .64 2500 0 # Monitor Mode Control Register A\n"
"ctr siar .64 2508 0 # Sampled Instruction Address Register\n"
"ctr sdar .64 2516 0 # Sampled Data Address Register\n"
"ctr sier .64 2524 0 # Sampled Instruction Event Register\n"
"ctr sier2 .64 2532 0 # Sampled Instruction Event Register 2\n"
"ctr sier3 .64 2540 0 # Sampled Instruction Event Register 3\n"
"ctr mmcr3 .64 2548 0 # Monitor Mode Control Register 2\n"
"ctr dpdes .64 2556 0 # Directed Privileged Doorbell Exception State Register\n"
"ctr pc .64 2564 0 # Programm Counter\n"
"ctr cr0 .4 2572 0 # Condition Register Field 0\n"
"ctr cr1 .4 2573 0 # Condition Register Field 1\n"
"ctr cr2 .4 2574 0 # Condition Register Field 2\n"
"ctr cr3 .4 2575 0 # Condition Register Field 3\n"
"ctr cr4 .4 2576 0 # Condition Register Field 4\n"
"ctr cr5 .4 2577 0 # Condition Register Field 5\n"
"ctr cr6 .4 2578 0 # Condition Register Field 6\n"
"ctr cr7 .4 2579 0 # Condition Register Field 7\n"
"ctr ppr32 .32 2580 0 # Process Priority Register 32-bit\n"
"flg so .1 2584 0 # Summary Overflow\n"
"flg ov .1 2585 0 # Overflow\n"
"flg ca .1 2586 0 # Carry\n"
"gpr 0 .32 2587 0 # The zero register.\n";
return rz_str_dup(p);
}
}
static int analyze_op_vle(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask) {
vle_t *instr = NULL;
vle_handle handle = { 0 };
op->size = 2;
if (len > 1 && !vle_init(&handle, buf, len) && (instr = vle_next(&handle))) {
op->size = instr->size;
op->type = instr->analysis_op;
// op->id = instr->type;
if (mask & RZ_ANALYSIS_OP_MASK_DISASM) {
op->mnemonic = rz_str_dup(instr->name);
}
switch (op->type) {
case RZ_ANALYSIS_OP_TYPE_ILL:
break;
case RZ_ANALYSIS_OP_TYPE_ADD:
break;
case RZ_ANALYSIS_OP_TYPE_AND:
break;
case RZ_ANALYSIS_OP_TYPE_CALL:
op->jump = addr + instr->fields[instr->n - 1].value;
op->fail = addr + op->size;
break;
case RZ_ANALYSIS_OP_TYPE_CCALL:
op->eob = true;
op->jump = addr + instr->fields[instr->n - 1].value;
op->fail = addr + op->size;
break;
case RZ_ANALYSIS_OP_TYPE_CJMP:
op->cond = instr->cond; // RZ_TYPE_COND_NE;
op->eob = true;
op->jump = addr + instr->fields[instr->n - 1].value;
op->fail = addr + op->size;
break;
case RZ_ANALYSIS_OP_TYPE_CMP:
break;
case RZ_ANALYSIS_OP_TYPE_JMP:
op->jump = addr + instr->fields[instr->n - 1].value;
break;
case RZ_ANALYSIS_OP_TYPE_LOAD:
break;
case RZ_ANALYSIS_OP_TYPE_MOV:
break;
case RZ_ANALYSIS_OP_TYPE_MUL:
break;
case RZ_ANALYSIS_OP_TYPE_NOT:
break;
case RZ_ANALYSIS_OP_TYPE_OR:
break;
case RZ_ANALYSIS_OP_TYPE_ROR:
break;
case RZ_ANALYSIS_OP_TYPE_ROL:
break;
case RZ_ANALYSIS_OP_TYPE_RCALL:
op->eob = true;
break;
case RZ_ANALYSIS_OP_TYPE_RET:
op->eob = true;
break;
case RZ_ANALYSIS_OP_TYPE_RJMP:
break;
case RZ_ANALYSIS_OP_TYPE_SHL:
break;
case RZ_ANALYSIS_OP_TYPE_SHR:
break;
case RZ_ANALYSIS_OP_TYPE_STORE:
break;
case RZ_ANALYSIS_OP_TYPE_SUB:
break;
case RZ_ANALYSIS_OP_TYPE_SWI:
break;
case RZ_ANALYSIS_OP_TYPE_SYNC:
break;
case RZ_ANALYSIS_OP_TYPE_TRAP:
break;
case RZ_ANALYSIS_OP_TYPE_XOR:
break;
default:
// RZ_LOG_ERROR("Missing an RZ_ANALYSIS_OP_TYPE (%"PFMT64u")\n", op->type);
break;
}
vle_free(instr);
return op->size;
}
return -1;
}
static int parse_reg_name(RzRegItem *reg, csh handle, cs_insn *insn, int reg_num) {
if (!reg) {
return -1;
}
switch (INSOP(reg_num).type) {
case PPC_OP_REG:
reg->name = (char *)cs_reg_name(handle, INSOP(reg_num).reg);
break;
case PPC_OP_MEM:
if (INSOP(reg_num).mem.base != PPC_REG_INVALID) {
reg->name = (char *)cs_reg_name(handle, INSOP(reg_num).mem.base);
}
break;
default:
break;
}
return 0;
}
static void create_src_dst(RzAnalysisOp *op, PPCContext *ctx) {
op->src[0] = rz_analysis_value_new();
op->src[1] = rz_analysis_value_new();
op->src[2] = rz_analysis_value_new();
op->dst = rz_analysis_value_new();
ZERO_FILL(ctx->base_regs[0]);
ZERO_FILL(ctx->base_regs[1]);
ZERO_FILL(ctx->base_regs[2]);
ZERO_FILL(ctx->base_regs[3]);
}
static void set_src_dst(RzAnalysisValue *val, csh *handle, cs_insn *insn, int x, PPCContext *ctx) {
cs_ppc_op ppcop = INSOP(x);
parse_reg_name(&ctx->base_regs[x], *handle, insn, x);
switch (ppcop.type) {
case PPC_OP_REG:
break;
case PPC_OP_MEM:
val->delta = ppcop.mem.disp;
break;
case PPC_OP_IMM:
val->imm = ppcop.imm;
break;
default:
break;
}
val->reg = &ctx->base_regs[x];
}
static void op_fillval(RzAnalysisOp *op, csh handle, cs_insn *insn, PPCContext *ctx) {
create_src_dst(op, ctx);
switch (op->type & RZ_ANALYSIS_OP_TYPE_MASK) {
case RZ_ANALYSIS_OP_TYPE_MOV:
case RZ_ANALYSIS_OP_TYPE_CMP:
case RZ_ANALYSIS_OP_TYPE_ADD:
case RZ_ANALYSIS_OP_TYPE_SUB:
case RZ_ANALYSIS_OP_TYPE_MUL:
case RZ_ANALYSIS_OP_TYPE_DIV:
case RZ_ANALYSIS_OP_TYPE_SHR:
case RZ_ANALYSIS_OP_TYPE_SHL:
case RZ_ANALYSIS_OP_TYPE_SAL:
case RZ_ANALYSIS_OP_TYPE_SAR:
case RZ_ANALYSIS_OP_TYPE_OR:
case RZ_ANALYSIS_OP_TYPE_AND:
case RZ_ANALYSIS_OP_TYPE_XOR:
case RZ_ANALYSIS_OP_TYPE_NOR:
case RZ_ANALYSIS_OP_TYPE_NOT:
case RZ_ANALYSIS_OP_TYPE_LOAD:
case RZ_ANALYSIS_OP_TYPE_LEA:
case RZ_ANALYSIS_OP_TYPE_ROR:
case RZ_ANALYSIS_OP_TYPE_ROL:
case RZ_ANALYSIS_OP_TYPE_CAST:
set_src_dst(op->src[2], &handle, insn, 3, ctx);
set_src_dst(op->src[1], &handle, insn, 2, ctx);
set_src_dst(op->src[0], &handle, insn, 1, ctx);
set_src_dst(op->dst, &handle, insn, 0, ctx);
break;
case RZ_ANALYSIS_OP_TYPE_STORE:
set_src_dst(op->dst, &handle, insn, 1, ctx);
set_src_dst(op->src[0], &handle, insn, 0, ctx);
break;
}
}
static char *shrink(char *op) {
if (!op) {
return NULL;
}
size_t len = strlen(op);
if (!len) {
return NULL;
}
op[len - 1] = 0;
return op;
}
static int ppc_analyze_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask) {
PPCContext *ctx = (PPCContext *)a->plugin_data;
int n, ret;
cs_insn *insn;
char *op1;
int mode = (a->bits == 64) ? CS_MODE_64 : (a->bits == 32) ? CS_MODE_32
: 0;
mode |= a->big_endian ? CS_MODE_BIG_ENDIAN : CS_MODE_LITTLE_ENDIAN;
if (a->cpu && strncmp(a->cpu, "vle", 3) == 0) {
// vle is big-endian only
if (!a->big_endian) {
return -1;
}
ret = analyze_op_vle(a, op, addr, buf, len, mask);
if (ret >= 0) {
return op->size;
}
} else if (a->cpu && RZ_STR_EQ(a->cpu, "qpx")) {
mode |= CS_MODE_QPX;
}
if (mode != ctx->omode || a->bits != ctx->obits) {
cs_close(&ctx->handle);
ctx->handle = 0;
ctx->omode = mode;
ctx->obits = a->bits;
}
if (ctx->handle == 0) {
ret = cs_open(CS_ARCH_PPC, mode, &ctx->handle);
if (ret != CS_ERR_OK) {
return -1;
}
cs_option(ctx->handle, CS_OPT_DETAIL, CS_OPT_ON);
#if CS_NEXT_VERSION >= 6
cs_option(ctx->handle, CS_OPT_DETAIL, CS_OPT_DETAIL_REAL);
#endif
}
op->size = 4;
// capstone-next
n = cs_disasm(ctx->handle, (const ut8 *)buf, len, addr, 1, &insn);
if (n < 1) {
op->type = RZ_ANALYSIS_OP_TYPE_ILL;
op->il_op = rz_il_op_new_empty();
} else {
op->il_op = rz_ppc_cs_get_il_op(ctx->handle, insn, mode);
if (mask & RZ_ANALYSIS_OP_MASK_DISASM) {
op->mnemonic = rz_str_dup(insn->mnemonic);
}
if (mask & RZ_ANALYSIS_OP_MASK_OPEX) {
op->opex = ppc_opex(ctx->handle, insn);
}
struct Getarg gop = {
.handle = ctx->handle,
.insn = insn,
.bits = a->bits
};
op->size = insn->size;
op->id = insn->id;
switch (insn->id) {
case PPC_INS_CMPB:
case PPC_INS_CMPD:
case PPC_INS_CMPDI:
case PPC_INS_CMPLD:
case PPC_INS_CMPLDI:
case PPC_INS_CMPLW:
case PPC_INS_CMPLWI:
case PPC_INS_CMPW:
case PPC_INS_CMPWI:
#if CS_API_MAJOR == 5 && CS_NEXT_VERSION < 6
case PPC_INS_CMP:
case PPC_INS_CMPI:
#endif
op->type = RZ_ANALYSIS_OP_TYPE_CMP;
op->sign = true;
/* 0b01 == equal
* 0b10 == less than */
if (ARG(2)[0] == '\0') {
esilprintf(op, ",%s,%s,-,!,cr0,=,%s,%s,<,?{2,cr0,|=,}", ARG(1), ARG(0), ARG(1), ARG(0));
} else {
esilprintf(op, ",%s,%s,-,!,%s,=,%s,%s,<,?{2,%s,|=,}", ARG(2), ARG(1), ARG(0), ARG(2), ARG(1), ARG(0));
}
break;
case PPC_INS_MFLR:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
esilprintf(op, "lr,%s,=", ARG(0));
break;
case PPC_INS_MTLR:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
esilprintf(op, "%s,lr,=", ARG(0));
break;
#if CS_NEXT_VERSION < 6
case PPC_INS_CLRLWI:
op->type = RZ_ANALYSIS_OP_TYPE_AND;
esilprintf(op, "%s,%s,&,%s,=", ARG(1), cmask32(a, ARG(2), "0x1F"), ARG(0));
break;
case PPC_INS_MR:
#endif
case PPC_INS_LI:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
op->val = IMM(1);
esilprintf(op, "%s,%s,=", ARG(1), ARG(0));
break;
case PPC_INS_LIS:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
op->val = IMM(1);
op->val <<= 16;
esilprintf(op, "%s0000,%s,=", ARG(1), ARG(0));
break;
case PPC_INS_RLWINM:
op->type = RZ_ANALYSIS_OP_TYPE_ROL;
esilprintf(op, "%s,%s,<<<,%s,&,%s,=", ARG(2), ARG(1), cmask32(a, ARG(3), ARG(4)), ARG(0));
break;
case PPC_INS_SC:
op->type = RZ_ANALYSIS_OP_TYPE_SWI;
esilprintf(op, "0,$");
break;
case PPC_INS_EXTSB:
op->sign = true;
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
if (a->bits == 64) {
esilprintf(op, "%s,0x80,&,?{,0xFFFFFFFFFFFFFF00,%s,|,%s,=,}", ARG(1), ARG(1), ARG(0));
} else {
esilprintf(op, "%s,0x80,&,?{,0xFFFFFF00,%s,|,%s,=,}", ARG(1), ARG(1), ARG(0));
}
break;
case PPC_INS_EXTSH:
op->sign = true;
if (a->bits == 64) {
esilprintf(op, "%s,0x8000,&,?{,0xFFFFFFFFFFFF0000,%s,|,%s,=,}", ARG(1), ARG(1), ARG(0));
} else {
esilprintf(op, "%s,0x8000,&,?{,0xFFFF0000,%s,|,%s,=,}", ARG(1), ARG(1), ARG(0));
}
break;
case PPC_INS_EXTSW:
op->sign = true;
esilprintf(op, "%s,0x80000000,&,?{,0xFFFFFFFF00000000,%s,|,%s,=,}", ARG(1), ARG(1), ARG(0));
break;
case PPC_INS_SYNC:
case PPC_INS_ISYNC:
#if CS_NEXT_VERSION < 6
case PPC_INS_LWSYNC:
case PPC_INS_MSYNC:
case PPC_INS_PTESYNC:
#endif
case PPC_INS_TLBSYNC:
case PPC_INS_SLBIA:
case PPC_INS_SLBIE:
case PPC_INS_SLBMFEE:
case PPC_INS_SLBMTE:
case PPC_INS_EIEIO:
case PPC_INS_NOP:
op->type = RZ_ANALYSIS_OP_TYPE_NOP;
esilprintf(op, ",");
break;
case PPC_INS_STW:
case PPC_INS_STWUX:
case PPC_INS_STWX:
case PPC_INS_STWCX:
op->type = RZ_ANALYSIS_OP_TYPE_STORE;
esilprintf(op, "%s,%s", ARG(0), ARG2(1, "=[4]"));
break;
case PPC_INS_STWU:
op->type = RZ_ANALYSIS_OP_TYPE_STORE;
op1 = shrink(ARG(1));
if (!op1) {
break;
}
esilprintf(op, "%s,%s,=[4],%s=", ARG(0), op1, op1);
if (strstr(op1, "r1")) {
op->stackop = RZ_ANALYSIS_STACK_INC;
op->stackptr = -atoi(op1);
}
break;
case PPC_INS_STWBRX:
op->type = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case PPC_INS_STB:
op->type = RZ_ANALYSIS_OP_TYPE_STORE;
esilprintf(op, "%s,%s", ARG(0), ARG2(1, "=[1]"));
break;
case PPC_INS_STBU:
op->type = RZ_ANALYSIS_OP_TYPE_STORE;
op1 = shrink(ARG(1));
if (!op1) {
break;
}
esilprintf(op, "%s,%s,=[1],%s=", ARG(0), op1, op1);
break;
case PPC_INS_STH:
op->type = RZ_ANALYSIS_OP_TYPE_STORE;
esilprintf(op, "%s,%s", ARG(0), ARG2(1, "=[2]"));
break;
case PPC_INS_STHU:
op->type = RZ_ANALYSIS_OP_TYPE_STORE;
op1 = shrink(ARG(1));
if (!op1) {
break;
}
esilprintf(op, "%s,%s,=[2],%s=", ARG(0), op1, op1);
break;
case PPC_INS_STD:
op->type = RZ_ANALYSIS_OP_TYPE_STORE;
esilprintf(op, "%s,%s", ARG(0), ARG2(1, "=[8]"));
break;
case PPC_INS_STDU:
op->type = RZ_ANALYSIS_OP_TYPE_STORE;
op1 = shrink(ARG(1));
if (!op1) {
break;
}
esilprintf(op, "%s,%s,=[8],%s=", ARG(0), op1, op1);
break;
case PPC_INS_LBZ:
case PPC_INS_LBZCIX:
case PPC_INS_LBZU:
case PPC_INS_LBZUX:
op->type = RZ_ANALYSIS_OP_TYPE_LOAD;
op1 = shrink(ARG(1));
if (!op1) {
break;
}
esilprintf(op, "%s,[1],%s,=,%s=", op1, ARG(0), op1);
break;
case PPC_INS_LBZX:
op->type = RZ_ANALYSIS_OP_TYPE_LOAD;
esilprintf(op, "%s,%s,=", ARG2(1, "[1]"), ARG(0));
break;
case PPC_INS_LD:
case PPC_INS_LDARX:
case PPC_INS_LDCIX:
case PPC_INS_LDU:
case PPC_INS_LDUX:
op->type = RZ_ANALYSIS_OP_TYPE_LOAD;
op1 = shrink(ARG(1));
if (!op1) {
break;
}
esilprintf(op, "%s,[8],%s,=,%s=", op1, ARG(0), op1);
break;
case PPC_INS_LDX:
op->type = RZ_ANALYSIS_OP_TYPE_LOAD;
esilprintf(op, "%s,%s,=", ARG2(1, "[8]"), ARG(0));
break;
case PPC_INS_LDBRX:
op->type = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case PPC_INS_LFD:
case PPC_INS_LFDU:
case PPC_INS_LFDUX:
case PPC_INS_LFDX:
case PPC_INS_LFIWAX:
case PPC_INS_LFIWZX:
case PPC_INS_LFS:
case PPC_INS_LFSU:
case PPC_INS_LFSUX:
case PPC_INS_LFSX:
op->type = RZ_ANALYSIS_OP_TYPE_LOAD;
esilprintf(op, "%s,%s,=", ARG2(1, "[4]"), ARG(0));
break;
case PPC_INS_LHA:
case PPC_INS_LHAU:
case PPC_INS_LHAUX:
case PPC_INS_LHAX:
case PPC_INS_LHZ:
case PPC_INS_LHZU:
op->type = RZ_ANALYSIS_OP_TYPE_LOAD;
op1 = shrink(ARG(1));
if (!op1) {
break;
}
esilprintf(op, "%s,[2],%s,=,%s=", op1, ARG(0), op1);
break;
case PPC_INS_LHBRX:
op->type = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case PPC_INS_LWA:
case PPC_INS_LWARX:
case PPC_INS_LWAUX:
case PPC_INS_LWAX:
case PPC_INS_LWZ:
case PPC_INS_LWZCIX:
case PPC_INS_LWZX:
op->type = RZ_ANALYSIS_OP_TYPE_LOAD;
esilprintf(op, "%s,%s,=", ARG2(1, "[4]"), ARG(0));
break;
case PPC_INS_LWZU:
case PPC_INS_LWZUX:
op->type = RZ_ANALYSIS_OP_TYPE_LOAD;
op1 = shrink(ARG(1));
if (!op1) {
break;
}
esilprintf(op, "%s,[4],%s,=,%s=", op1, ARG(0), op1);
break;
case PPC_INS_LWBRX:
op->type = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case PPC_INS_SLW:
case PPC_INS_SLWI:
op->type = RZ_ANALYSIS_OP_TYPE_SHL;
esilprintf(op, "%s,%s,<<,%s,=", ARG(2), ARG(1), ARG(0));
break;
case PPC_INS_SRW:
case PPC_INS_SRWI:
op->type = RZ_ANALYSIS_OP_TYPE_SHR;
esilprintf(op, "%s,%s,>>,%s,=", ARG(2), ARG(1), ARG(0));
break;
case PPC_INS_MULLI:
op->sign = true;
// fallthrough
case PPC_INS_MULLW:
case PPC_INS_MULLD:
op->type = RZ_ANALYSIS_OP_TYPE_MUL;
esilprintf(op, "%s,%s,*,%s,=", ARG(2), ARG(1), ARG(0));
break;
#if CS_NEXT_VERSION < 6
case PPC_INS_SUB:
case PPC_INS_SUBC:
#endif
case PPC_INS_SUBF:
case PPC_INS_SUBFIC:
case PPC_INS_SUBFZE:
op->type = RZ_ANALYSIS_OP_TYPE_SUB;
esilprintf(op, "%s,%s,-,%s,=", ARG(1), ARG(2), ARG(0));
break;
case PPC_INS_ADDI:
op->val = ((st16)IMM(2));
op->sign = true;
op->type = RZ_ANALYSIS_OP_TYPE_ADD;
esilprintf(op, "%" PFMT64d ",%s,+,%s,=", (st64)op->val, ARG(1), ARG(0));
break;
case PPC_INS_ADD:
op->sign = true;
op->type = RZ_ANALYSIS_OP_TYPE_ADD;
esilprintf(op, "%s,%s,+,%s,=", ARG(2), ARG(1), ARG(0));
break;
#if CS_NEXT_VERSION < 6
case PPC_INS_CRCLR:
case PPC_INS_CRSET:
case PPC_INS_CRMOVE:
case PPC_INS_CRNOT:
#endif
case PPC_INS_CRXOR:
case PPC_INS_CRNOR:
// reset conditional bits
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
break;
case PPC_INS_ADDC:
case PPC_INS_ADDIC:
op->type = RZ_ANALYSIS_OP_TYPE_ADD;
esilprintf(op, "%s,%s,+,%s,=", ARG(2), ARG(1), ARG(0));
break;
case PPC_INS_ADDE:
case PPC_INS_ADDIS:
case PPC_INS_ADDME:
case PPC_INS_ADDZE:
#if CS_NEXT_VERSION >= 6
switch (insn->alias_id) {
default:
op->type = RZ_ANALYSIS_OP_TYPE_ADD;
esilprintf(op, "%s,%s,+,%s,=", ARG(2), ARG(1), ARG(0));
break;
case PPC_INS_ALIAS_LIS:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
op->val = IMM(2);
op->val <<= 16;
esilprintf(op, "0x%" PFMT64x "0000,%s,=", IMM(2), ARG(0));
break;
}
#else
op->type = RZ_ANALYSIS_OP_TYPE_ADD;
esilprintf(op, "%s,%s,+,%s,=", ARG(2), ARG(1), ARG(0));
#endif
break;
case PPC_INS_MTSPR:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
esilprintf(op, "%s,%s,=", ARG(1), PPCSPR(0));
break;
case PPC_INS_BCTR: // switch table here
op->type = RZ_ANALYSIS_OP_TYPE_UJMP;
esilprintf(op, "ctr,pc,=");
break;
case PPC_INS_BCTRL: // switch table here
op->type = RZ_ANALYSIS_OP_TYPE_CALL;
esilprintf(op, "pc,lr,=,ctr,pc,=");
break;
#if CS_API_MAJOR == 5 && CS_NEXT_VERSION < 6
case PPC_INS_BEQ:
case PPC_INS_BEQA:
case PPC_INS_BFA:
case PPC_INS_BGE:
case PPC_INS_BGEA:
case PPC_INS_BGT:
case PPC_INS_BGTA:
case PPC_INS_BLE:
case PPC_INS_BLEA:
case PPC_INS_BLT:
case PPC_INS_BLTA:
case PPC_INS_BNE:
case PPC_INS_BNEA:
case PPC_INS_BNG:
case PPC_INS_BNGA:
case PPC_INS_BNL:
case PPC_INS_BNLA:
case PPC_INS_BNS:
case PPC_INS_BNSA:
case PPC_INS_BNU:
case PPC_INS_BNUA:
case PPC_INS_BSO:
case PPC_INS_BSOA:
case PPC_INS_BUN:
case PPC_INS_BUNA:
#endif
#if CS_NEXT_VERSION < 6
case PPC_INS_BT:
case PPC_INS_BF:
switch (insn->detail->ppc.operands[0].type) {
case PPC_OP_CRX:
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
op->fail = addr + op->size;
break;
case PPC_OP_REG:
if (op->type == RZ_ANALYSIS_OP_TYPE_CJMP) {
op->type = RZ_ANALYSIS_OP_TYPE_UCJMP;
} else {
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
}
op->jump = IMM(1);
op->fail = addr + op->size;
// op->type = RZ_ANALYSIS_OP_TYPE_UJMP;
default:
break;
}
break;
case PPC_INS_BDNZ:
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
op->jump = IMM(0);
op->fail = addr + op->size;
esilprintf(op, "1,ctr,-=,$z,!,?{,%s,pc,=,}", ARG(0));
break;
case PPC_INS_BDNZA:
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
op->jump = IMM(0);
op->fail = addr + op->size;
break;
case PPC_INS_BDNZL:
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
op->jump = IMM(0);
op->fail = addr + op->size;
break;
case PPC_INS_BDNZLA:
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
op->jump = IMM(0);
op->fail = addr + op->size;
break;
case PPC_INS_BDNZLR:
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
op->fail = addr + op->size;
esilprintf(op, "1,ctr,-=,$z,!,?{,lr,pc,=,},");
break;
case PPC_INS_BDNZLRL:
op->fail = addr + op->size;
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
break;
case PPC_INS_BDZ:
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
op->jump = IMM(0);
op->fail = addr + op->size;
esilprintf(op, "1,ctr,-=,$z,?{,%s,pc,=,}", ARG(0));
break;
case PPC_INS_BDZA:
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
op->jump = IMM(0);
op->fail = addr + op->size;
break;
case PPC_INS_BDZL:
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
op->jump = IMM(0);
op->fail = addr + op->size;
break;
case PPC_INS_BDZLA:
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
op->jump = IMM(0);
op->fail = addr + op->size;
break;
case PPC_INS_BDZLR:
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
op->fail = addr + op->size;
esilprintf(op, "1,ctr,-=,$z,?{,lr,pc,=,}");
break;
case PPC_INS_BDZLRL:
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
op->fail = addr + op->size;
break;
#endif
case PPC_INS_B:
case PPC_INS_BC:
case PPC_INS_BA:
case PPC_INS_BCL:
case PPC_INS_BLR:
case PPC_INS_BLRL:
case PPC_INS_BCLR:
case PPC_INS_BCLRL:
case PPC_INS_BCCTR:
case PPC_INS_BCCTRL: {
if (insn->id == PPC_INS_BC || insn->id == PPC_INS_BCCTR) {
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
} else if (insn->id == PPC_INS_B || insn->id == PPC_INS_BA) {
op->type = RZ_ANALYSIS_OP_TYPE_JMP;
} else if (insn->id == PPC_INS_BCLR || insn->id == PPC_INS_BCLRL) {
op->type = RZ_ANALYSIS_OP_TYPE_CRET;
} else if (insn->id == PPC_INS_BLR || insn->id == PPC_INS_BLRL) {
op->type = RZ_ANALYSIS_OP_TYPE_RET;
} else if (insn->id == PPC_INS_BCCTRL) {
op->type = RZ_ANALYSIS_OP_TYPE_CCALL;
}
bool cr_cond_set = true;
bool ctr_cond_set = true;
#if CS_NEXT_VERSION >= 6
switch (insn->detail->ppc.bc.pred_cr) {
case PPC_PRED_LT:
esilprintf(op, "2,%s,&,", cs_reg_name(ctx->handle, insn->detail->ppc.bc.crX));
#else
switch (insn->detail->ppc.bc) {
case PPC_BC_LT:
if (ARG(1)[0] == '\0') {
esilprintf(op, "2,cr0,&,");
} else {
esilprintf(op, "2,%s,&,", ARG(0));
}
#endif
break;
#if CS_NEXT_VERSION >= 6
case PPC_PRED_LE:
esilprintf(op, "3,%s,&,", cs_reg_name(ctx->handle, insn->detail->ppc.bc.crX));
#else
case PPC_BC_LE:
/* 0b01 == equal
* 0b10 == less than */
if (ARG(1)[0] == '\0') {
esilprintf(op, "3,cr0,&,?{,%s,pc,=,},", ARG(0));
} else {
esilprintf(op, "3,%s,&,?{,%s,pc,=,},", ARG(0), ARG(1));
}
#endif
break;
#if CS_NEXT_VERSION >= 6
case PPC_PRED_EQ:
esilprintf(op, "1,%s,&,", cs_reg_name(ctx->handle, insn->detail->ppc.bc.crX));
#else
case PPC_BC_EQ:
if (ARG(1)[0] == '\0') {
esilprintf(op, "1,cr0,&,");
} else {
esilprintf(op, "1,%s,&,", ARG(0));
}
#endif
break;
#if CS_NEXT_VERSION >= 6
case PPC_PRED_GE:
esilprintf(op, "2,%s,^,3,&,", cs_reg_name(ctx->handle, insn->detail->ppc.bc.crX));
#else
case PPC_BC_GE:
if (ARG(1)[0] == '\0') {
esilprintf(op, "2,cr0,^,3,&,");
} else {
esilprintf(op, "2,%s,^,3,&,", ARG(0));
}
#endif
break;
#if CS_NEXT_VERSION >= 6
case PPC_PRED_GT:
esilprintf(op, "2,%s,&,!,", cs_reg_name(ctx->handle, insn->detail->ppc.bc.crX));
#else
case PPC_BC_GT:
if (ARG(1)[0] == '\0') {
esilprintf(op, "2,cr0,&,!,");
} else {
esilprintf(op, "2,%s,&,!,", ARG(0));
}
#endif
break;
#if CS_NEXT_VERSION >= 6
case PPC_PRED_NE:
esilprintf(op, "%s,1,&,!,", cs_reg_name(ctx->handle, insn->detail->ppc.bc.crX));
#else
case PPC_BC_NE:
if (ARG(1)[0] == '\0') {
esilprintf(op, "cr0,1,&,!,");
} else {
esilprintf(op, "%s,1,&,!,", ARG(0));
}
#endif
break;
#if CS_NEXT_VERSION >= 6
case PPC_PRED_INVALID:
case PPC_PRED_UN: // unordered + PPC_PRED_SO - summary overflow
case PPC_PRED_NU: // not unordered + PPC_PRED_NS - not summary overflow
#else
case PPC_BC_INVALID:
case PPC_BC_UN: // unordered
case PPC_BC_NU: // not unordered
case PPC_BC_SO: // summary overflow
case PPC_BC_NS: // not summary overflow
#endif
default:
cr_cond_set = false;
break;
}
#if CS_NEXT_VERSION >= 6
switch (insn->detail->ppc.bc.pred_ctr) {
default:
ctr_cond_set = false;
break;
case PPC_PRED_Z:
rz_strbuf_appendf(&op->esil, "1,ctr,-=,$z,%s", cr_cond_set ? "&&,?" : "?");
break;
case PPC_PRED_NZ:
rz_strbuf_appendf(&op->esil, "1,ctr,-=,$z,!,%s", cr_cond_set ? "&&,?" : "?");
break;
}
#endif
bool is_cond = cr_cond_set || ctr_cond_set;
if (is_cond) {
rz_strbuf_appendf(&op->esil, "{,");
op->fail = addr + op->size;
}
if (insn->id == PPC_INS_B || insn->id == PPC_INS_BC || insn->id == PPC_INS_BA || insn->id == PPC_INS_BCL) {
#if CS_NEXT_VERSION >= 6
op->jump = (insn->id == PPC_INS_BC || insn->id == PPC_INS_BCL) ? IMM(2) : IMM(0);
#else
op->jump = ARG(1)[0] == '\0' ? IMM(0) : IMM(1);
#endif
}
if (insn->id == PPC_INS_BLRL ||
insn->id == PPC_INS_BCLRL ||
insn->id == PPC_INS_BCCTRL ||
insn->id == PPC_INS_BCL) {
op->fail = addr + op->size;
rz_strbuf_appendf(&op->esil, "0x%" PFMT64x ",lr,=,", op->fail);
}
// Set target source
if (insn->id == PPC_INS_BCCTR || insn->id == PPC_INS_BCCTRL) {
rz_strbuf_appendf(&op->esil, "ctr,pc,=,");
} else if (op->type == RZ_ANALYSIS_OP_TYPE_CRET || op->type == RZ_ANALYSIS_OP_TYPE_RET) {
rz_strbuf_appendf(&op->esil, "lr,pc,=,");
} else {
rz_strbuf_appendf(&op->esil, "0x%" PFMT64x ",pc,=,", op->jump);
}
if (is_cond) {
rz_strbuf_appendf(&op->esil, "},");
}
break;
}
case PPC_INS_NOR:
op->type = RZ_ANALYSIS_OP_TYPE_NOR;
esilprintf(op, "%s,%s,|,!,%s,=", ARG(2), ARG(1), ARG(0));
break;
case PPC_INS_XOR:
case PPC_INS_XORI:
op->type = RZ_ANALYSIS_OP_TYPE_XOR;
esilprintf(op, "%s,%s,^,%s,=", ARG(2), ARG(1), ARG(0));
break;
case PPC_INS_XORIS:
op->type = RZ_ANALYSIS_OP_TYPE_XOR;
esilprintf(op, "16,%s,<<,%s,^,%s,=", ARG(2), ARG(1), ARG(0));
break;
case PPC_INS_DIVD:
case PPC_INS_DIVW:
op->sign = true;
op->type = RZ_ANALYSIS_OP_TYPE_DIV;
esilprintf(op, "%s,%s,/,%s,=", ARG(2), ARG(1), ARG(0));
break;
case PPC_INS_DIVDU:
case PPC_INS_DIVWU:
op->type = RZ_ANALYSIS_OP_TYPE_DIV;
esilprintf(op, "%s,%s,/,%s,=", ARG(2), ARG(1), ARG(0));
break;
case PPC_INS_BL:
case PPC_INS_BLA:
op->type = RZ_ANALYSIS_OP_TYPE_CALL;
op->jump = IMM(0);
op->fail = addr + op->size;
esilprintf(op, "pc,lr,=,%s,pc,=", ARG(0));
break;
case PPC_INS_TRAP:
op->sign = true;
op->type = RZ_ANALYSIS_OP_TYPE_TRAP;
break;
case PPC_INS_AND:
case PPC_INS_NAND:
case PPC_INS_ANDI:
op->type = RZ_ANALYSIS_OP_TYPE_AND;
esilprintf(op, "%s,%s,&,%s,=", ARG(2), ARG(1), ARG(0));
break;
case PPC_INS_ANDIS:
op->type = RZ_ANALYSIS_OP_TYPE_AND;
esilprintf(op, "16,%s,<<,%s,&,%s,=", ARG(2), ARG(1), ARG(0));
break;
case PPC_INS_OR:
case PPC_INS_ORI:
op->type = RZ_ANALYSIS_OP_TYPE_OR;
esilprintf(op, "%s,%s,|,%s,=", ARG(2), ARG(1), ARG(0));
break;
case PPC_INS_ORIS:
op->type = RZ_ANALYSIS_OP_TYPE_OR;
esilprintf(op, "16,%s,<<,%s,|,%s,=", ARG(2), ARG(1), ARG(0));
break;
#if CS_NEXT_VERSION < 6
case PPC_INS_MFPVR:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
esilprintf(op, "pvr,%s,=", ARG(0));
break;
#endif
case PPC_INS_MFSPR:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
esilprintf(op, "%s,%s,=", PPCSPR(1), ARG(0));
break;
case PPC_INS_MFCTR:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
esilprintf(op, "ctr,%s,=", ARG(0));
break;
#if CS_NEXT_VERSION < 6
case PPC_INS_MFDCCR:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
esilprintf(op, "dccr,%s,=", ARG(0));
break;
case PPC_INS_MFICCR:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
esilprintf(op, "iccr,%s,=", ARG(0));
break;
case PPC_INS_MFDEAR:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
esilprintf(op, "dear,%s,=", ARG(0));
break;
#endif
case PPC_INS_MFMSR:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
esilprintf(op, "msr,%s,=", ARG(0));
break;
case PPC_INS_MTCTR:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
esilprintf(op, "%s,ctr,=", ARG(0));
break;
#if CS_NEXT_VERSION < 6
case PPC_INS_MTDCCR:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
esilprintf(op, "%s,dccr,=", ARG(0));
break;
case PPC_INS_MTICCR:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
esilprintf(op, "%s,iccr,=", ARG(0));
break;
case PPC_INS_MTDEAR:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
esilprintf(op, "%s,dear,=", ARG(0));
break;
#endif
case PPC_INS_MTMSR:
case PPC_INS_MTMSRD:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
esilprintf(op, "%s,msr,=", ARG(0));
break;
// Data Cache Block Zero
case PPC_INS_DCBZ:
op->type = RZ_ANALYSIS_OP_TYPE_STORE;
esilprintf(op, "%s,%s", ARG(0), ARG2(1, ",=[128]"));
break;
#if CS_NEXT_VERSION < 6
case PPC_INS_CLRLDI:
op->type = RZ_ANALYSIS_OP_TYPE_AND;
esilprintf(op, "%s,%s,&,%s,=", ARG(1), cmask64(a, ARG(2), "0x3F"), ARG(0));
break;
case PPC_INS_ROTLDI:
op->type = RZ_ANALYSIS_OP_TYPE_ROL;
esilprintf(op, "%s,%s,<<<,%s,=", ARG(2), ARG(1), ARG(0));
break;
#endif
case PPC_INS_RLDCL:
case PPC_INS_RLDICL:
op->type = RZ_ANALYSIS_OP_TYPE_ROL;
esilprintf(op, "%s,%s,<<<,%s,&,%s,=", ARG(2), ARG(1), cmask64(a, ARG(3), "0x3F"), ARG(0));
break;
case PPC_INS_RLDCR:
case PPC_INS_RLDICR:
op->type = RZ_ANALYSIS_OP_TYPE_ROL;
esilprintf(op, "%s,%s,<<<,%s,&,%s,=", ARG(2), ARG(1), cmask64(a, 0, ARG(3)), ARG(0));
break;
}
if (mask & RZ_ANALYSIS_OP_MASK_VAL) {
op_fillval(op, ctx->handle, insn, ctx);
}
if (!(mask & RZ_ANALYSIS_OP_MASK_ESIL)) {
rz_strbuf_fini(&op->esil);
}
cs_free(insn, n);
}
return op->size;
}
static int ppc_archinfo(RzAnalysis *a, RzAnalysisInfoType query) {
bool is_vle = a && a->cpu && !strncmp(a->cpu, "vle", 3);
switch (query) {
case RZ_ANALYSIS_ARCHINFO_MIN_OP_SIZE:
return is_vle ? 2 : 4;
case RZ_ANALYSIS_ARCHINFO_MAX_OP_SIZE:
return 4;
case RZ_ANALYSIS_ARCHINFO_TEXT_ALIGN:
return is_vle ? 2 : 4;
case RZ_ANALYSIS_ARCHINFO_DATA_ALIGN:
return 1;
case RZ_ANALYSIS_ARCHINFO_CAN_USE_POINTERS:
return true;
default:
return -1;
}
}
static RzList /*<RzSearchKeyword *>*/ *ppc_analysis_preludes(RzAnalysis *analysis) {
#define KW(d, ds, m, ms) rz_list_append(l, rz_search_keyword_new((const ut8 *)d, ds, (const ut8 *)m, ms, NULL))
RzList *l = rz_list_newf((RzListFree)rz_search_keyword_free);
KW("\x7c\x08\x02\xa6", 4, NULL, 0);
return l;
}
static RzAnalysisILConfig *ppc_il_config(RzAnalysis *analysis) {
if (analysis->bits == 64) {
return rz_ppc_cs_64_il_config(analysis->big_endian);
}
return rz_ppc_cs_32_il_config(analysis->big_endian);
}
static bool ppc_fini(void *user) {
PPCContext *ctx = (PPCContext *)user;
cs_close(&ctx->handle);
if (ctx) {
RZ_FREE(ctx);
}
return true;
}
RzAnalysisPlugin rz_analysis_plugin_ppc_cs = {
.name = "ppc",
.desc = "Capstone PowerPC analysis",
.license = "BSD",
.esil = true,
.arch = "ppc",
.bits = 32 | 64,
.archinfo = ppc_archinfo,
.preludes = ppc_analysis_preludes,
.op = &ppc_analyze_op,
.init = ppc_init,
.fini = ppc_fini,
.get_reg_profile = &ppc_get_reg_profile,
.il_config = ppc_il_config,
};
#ifndef RZ_PLUGIN_INCORE
RZ_API RzLibStruct rizin_plugin = {
.type = RZ_LIB_TYPE_ANALYSIS,
.data = &rz_analysis_plugin_ppc_cs,
.version = RZ_VERSION
};
#endif