Skip to content

Commit

Permalink
xtensa: add rzil support
Browse files Browse the repository at this point in the history
- addx2|4|8

- addmi

- addi|addi.n

- addexp.s addexpm.s

- addexp.s

- add|add.s|add.n

- abs
  • Loading branch information
imbillow committed Nov 11, 2024
1 parent 70654e8 commit dad52b0
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 1 deletion.
1 change: 1 addition & 0 deletions librz/arch/isa/xtensa/xtensa.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ bool xtensa_open(XtensaContext *ctx, const char *cpu, bool big_endian);
bool xtensa_disassemble(XtensaContext *self, const ut8 *buf, int len, ut64 addr);
void xtensa_disassemble_fini(XtensaContext *self);
void xtensa_analyze_op_esil(XtensaContext *ctx, RzAnalysisOp *op);
void xtensa_analyze_op_rzil(XtensaContext *ctx, RzAnalysisOp *op);

static inline cs_xtensa_op_mem *xtensa_op_mem(cs_insn *insn, unsigned int index) {
cs_xtensa_op *op = &insn->detail->xtensa.operands[index];
Expand Down
102 changes: 102 additions & 0 deletions librz/arch/isa/xtensa/xtensa_il.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// SPDX-FileCopyrightText: 2024 billow <[email protected]>
// SPDX-License-Identifier: LGPL-3.0-only

#include "xtensa.h"

#include <rz_il/rz_il_opbuilder_begin.h>

#define IREG(I) VARG(REGN(I))
#define ABS(X) ITE(SGT(X, S32(0)), X, NEG(X))

typedef RzAnalysisLiftedILOp (*fn_analyze_op_il)(XtensaContext *ctx);
typedef RzILOpPure *(fn_op2)(RzILOpBool *x, RzILOpBool *y);

static RzAnalysisLiftedILOp op_abs(XtensaContext *ctx) {
return SETG(REGN(0), ABS(IREG(1)));
}

static RzAnalysisLiftedILOp op_abs_s(XtensaContext *ctx) {
return SETG(REGN(0), UNSIGNED(64, F2BV(FABS(FLOATV32(IREG(1))))));
}

static RzAnalysisLiftedILOp op_add(XtensaContext *ctx) {
return SETG(REGN(0), ADD(IREG(1), IREG(2)));
}

static RzAnalysisLiftedILOp op_addi(XtensaContext *ctx) {
return SETG(REGN(0), ADD(IREG(1), S32(IMM(2))));
}

static RzAnalysisLiftedILOp op_addx2(XtensaContext *ctx) {
return SETG(REGN(0), ADD(SHIFTL0(IREG(1), U32(1)), IREG(2)));
}

static RzAnalysisLiftedILOp op_addx4(XtensaContext *ctx) {
return SETG(REGN(0), ADD(SHIFTL0(IREG(1), U32(2)), IREG(2)));
}

static RzAnalysisLiftedILOp op_addx8(XtensaContext *ctx) {
return SETG(REGN(0), ADD(SHIFTL0(IREG(1), U32(3)), IREG(2)));
}

// Fixme: statusflags
static RzAnalysisLiftedILOp op_add_s(XtensaContext *ctx) {
return SETG(REGN(0), UNSIGNED(64, F2BV(FADD(RZ_FLOAT_RMODE_RNA, FLOATV32(IREG(1)), FLOATV32(IREG(2))))));
}

static RzILOpPure *apply2_range2(RzILOpPure *self, fn_op2 fn, RzILOpPure *x, RzILOpPure *y,
unsigned begin1, unsigned begin2, unsigned length) {
return DEPOSIT64(
self,
U64(begin1), U32(length),
fn(EXTRACT64(x, U64(begin1), U32(length)), EXTRACT64(y, U64(begin2), U32(length))));
}

static RzILOpPure *f_add_sub127(RzILOpPure *x, RzILOpPure *y) {
return SUB(ADD(x, y), U64(127));
}

static RzAnalysisLiftedILOp op_addexp_s(XtensaContext *ctx) {
return SEQ3(
SETL("FRr", apply2_range2(IREG(0), rz_il_op_new_log_xor, IREG(0), IREG(1), 31, 31, 1)),
SETL("FRr", apply2_range2(VARL("FRr"), f_add_sub127, IREG(0), IREG(1), 23, 23, 8)),
SETG(REGN(0), VARL("FRr")));
}

static RzAnalysisLiftedILOp op_addexpm_s(XtensaContext *ctx) {
return SEQ3(
SETL("FRr", apply2_range2(IREG(0), rz_il_op_new_log_xor, IREG(0), IREG(1), 31, 22, 1)),
SETL("FRr", apply2_range2(VARL("FRr"), f_add_sub127, IREG(0), IREG(1), 23, 14, 8)),
SETG(REGN(0), VARL("FRr")));
}

#include <rz_il/rz_il_opbuilder_end.h>

static const fn_analyze_op_il fn_tbl[] = {
[XTENSA_INS_ABS] = op_abs,
[XTENSA_INS_ABS_S] = op_abs_s,
[XTENSA_INS_ADD] = op_add,
[XTENSA_INS_ADD_N] = op_add,
[XTENSA_INS_ADD_S] = op_add_s,
[XTENSA_INS_ADDEXP_S] = op_addexp_s,
[XTENSA_INS_ADDEXPM_S] = op_addexpm_s,
[XTENSA_INS_ADDI] = op_addi,
[XTENSA_INS_ADDI_N] = op_addi,
[XTENSA_INS_ADDMI] = op_addi,
[XTENSA_INS_ADDX2] = op_addx2,
[XTENSA_INS_ADDX4] = op_addx4,
[XTENSA_INS_ADDX8] = op_addx8,
};

void xtensa_analyze_op_rzil(XtensaContext *ctx, RzAnalysisOp *op) {
unsigned id = ctx->insn->id;
if (id >= RZ_ARRAY_SIZE(fn_tbl)) {
return;
}

fn_analyze_op_il fn = fn_tbl[id];
if (!fn) {
return;
}
op->il_op = fn(ctx);
}
30 changes: 30 additions & 0 deletions librz/arch/p/analysis/analysis_xtensa_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
#include <rz_endian.h>
#include <xtensa/xtensa.h>

RzAnalysisILConfig *xtensa_il_config(RzAnalysis *a) {
rz_return_val_if_fail(a, NULL);

RzAnalysisILConfig *cfg = rz_analysis_il_config_new(32, a->big_endian, 32);
// cfg->reg_bindings = xtensa_registers;
return cfg;
}

static int xtensa_archinfo(RzAnalysis *a, RzAnalysisInfoType query) {
switch (query) {
case RZ_ANALYSIS_ARCHINFO_MIN_OP_SIZE:
Expand Down Expand Up @@ -58,6 +66,23 @@ static char *xtensa_get_reg_profile(RzAnalysis *analysis) {
"gpr a14 .32 60 0\n"
"gpr a15 .32 64 0\n"

"gpr f0 .64 76 0\n"
"gpr f1 .64 84 0\n"
"gpr f2 .64 92 0\n"
"gpr f3 .64 100 0\n"
"gpr f4 .64 108 0\n"
"gpr f5 .64 116 0\n"
"gpr f6 .64 124 0\n"
"gpr f7 .64 132 0\n"
"gpr f8 .64 140 0\n"
"gpr f9 .64 148 0\n"
"gpr f10 .64 156 0\n"
"gpr f11 .64 164 0\n"
"gpr f12 .64 172 0\n"
"gpr f13 .64 180 0\n"
"gpr f14 .64 188 0\n"
"gpr f15 .64 196 0\n"

// pc
"gpr pc .32 68 0\n"

Expand Down Expand Up @@ -339,6 +364,10 @@ static int xtensa_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut
xtensa_analyze_op_esil(ctx, op);
}

if (mask & RZ_ANALYSIS_OP_MASK_IL){
xtensa_analyze_op_rzil(ctx, op);
}

op->size = ctx->insn->size;
op->id = ctx->insn->id;
op->addr = addr;
Expand All @@ -359,6 +388,7 @@ RzAnalysisPlugin rz_analysis_plugin_xtensa_cs = {
.bits = 8,
.op = xtensa_op,
.esil = true,
.il_config = xtensa_il_config,
.archinfo = xtensa_archinfo,
.get_reg_profile = xtensa_get_reg_profile,
.init = xtensa_init,
Expand Down
13 changes: 13 additions & 0 deletions test/db/asm/xtensa
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
d "abs a1, a0" 001160 0x0 (set a1 (ite (! (sle (var a0) (bv 32 0x0))) (var a0) (~- (var a0))))
d "abs.s f1, f2" 1012fa 0x0 (set f1 (cast 64 false (fbits (fpos (float 0 (var f2) )))))
d "add a0, a0, a0" 000080 0x0 (set a0 (+ (var a0) (var a0)))
d "add.s f0, f0, f0" 00000a 0x0 (set f0 (cast 64 false (fbits (+. rna (float 0 (var f0) ) (float 0 (var f0) )))))
d "add.n a0, a0, a0" 0a00 0x0 (set a0 (+ (var a0) (var a0)))
d "addexp.s f0, f1" e001fa 0x0 (seq (set FRr (| (& (var f0) (~ (<< (>> (bv 64 0xffffffffffffffff) (- (bv 32 0x40) (bv 32 0x1)) false) (bv 64 0x1f) false))) (& (<< (^ (& (>> (var f0) (bv 64 0x1f) false) (>> (bv 64 0xffffffffffffffff) (- (bv 32 0x40) (bv 32 0x1)) false)) (& (>> (var f1) (bv 64 0x1f) false) (>> (bv 64 0xffffffffffffffff) (- (bv 32 0x40) (bv 32 0x1)) false))) (bv 64 0x1f) false) (<< (>> (bv 64 0xffffffffffffffff) (- (bv 32 0x40) (bv 32 0x1)) false) (bv 64 0x1f) false)))) (set FRr (| (& (var FRr) (~ (<< (>> (bv 64 0xffffffffffffffff) (- (bv 32 0x40) (bv 32 0x8)) false) (bv 64 0x17) false))) (& (<< (- (+ (& (>> (var f0) (bv 64 0x17) false) (>> (bv 64 0xffffffffffffffff) (- (bv 32 0x40) (bv 32 0x8)) false)) (& (>> (var f1) (bv 64 0x17) false) (>> (bv 64 0xffffffffffffffff) (- (bv 32 0x40) (bv 32 0x8)) false))) (bv 64 0x7f)) (bv 64 0x17) false) (<< (>> (bv 64 0xffffffffffffffff) (- (bv 32 0x40) (bv 32 0x8)) false) (bv 64 0x17) false)))) (set f0 (var FRr)))
d "addexpm.s f1, f2" f012fa 0x0 (seq (set FRr (| (& (var f1) (~ (<< (>> (bv 64 0xffffffffffffffff) (- (bv 32 0x40) (bv 32 0x1)) false) (bv 64 0x1f) false))) (& (<< (^ (& (>> (var f1) (bv 64 0x1f) false) (>> (bv 64 0xffffffffffffffff) (- (bv 32 0x40) (bv 32 0x1)) false)) (& (>> (var f2) (bv 64 0x16) false) (>> (bv 64 0xffffffffffffffff) (- (bv 32 0x40) (bv 32 0x1)) false))) (bv 64 0x1f) false) (<< (>> (bv 64 0xffffffffffffffff) (- (bv 32 0x40) (bv 32 0x1)) false) (bv 64 0x1f) false)))) (set FRr (| (& (var FRr) (~ (<< (>> (bv 64 0xffffffffffffffff) (- (bv 32 0x40) (bv 32 0x8)) false) (bv 64 0x17) false))) (& (<< (- (+ (& (>> (var f1) (bv 64 0x17) false) (>> (bv 64 0xffffffffffffffff) (- (bv 32 0x40) (bv 32 0x8)) false)) (& (>> (var f2) (bv 64 0xe) false) (>> (bv 64 0xffffffffffffffff) (- (bv 32 0x40) (bv 32 0x8)) false))) (bv 64 0x7f)) (bv 64 0x17) false) (<< (>> (bv 64 0xffffffffffffffff) (- (bv 32 0x40) (bv 32 0x8)) false) (bv 64 0x17) false)))) (set f1 (var FRr)))
d "addi a3, a4, -1" 32c4ff 0x0 (set a3 (+ (var a4) (bv 32 0xffffffff)))
d "addi.n a2, a3, 1" 1b23 0x0 (set a2 (+ (var a3) (bv 32 0x1)))
d "addmi a3, a4, -0x100" 32d4ff 0x0 (set a3 (+ (var a4) (bv 32 0xffffff00)))
d "addx2 a2, a3, a1" 102390 0x0 (set a2 (+ (<< (var a3) (bv 32 0x1) false) (var a1)))
d "addx4 a2, a3, a1" 1023a0 0x0 (set a2 (+ (<< (var a3) (bv 32 0x2) false) (var a1)))
d "addx8 a2, a3, a1" 1023b0 0x0 (set a2 (+ (<< (var a3) (bv 32 0x3) false) (var a1)))
2 changes: 1 addition & 1 deletion test/db/cmd/cmd_list
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ a____ 16 32 64 x86.nasm LGPL3 X86 nasm assembler
a____ 16 32 64 x86.nz LGPL3 x86 handmade assembler
_dA__ 16 xap PD XAP4 RISC (CSR)
_dA__ 32 xcore BSD Capstone XCore disassembler (by pancake)
_dAe_ 32 xtensa LGPL3 Capstone Xtensa disassembly plugin (by billow)
_dAeI 32 xtensa LGPL3 Capstone Xtensa disassembly plugin (by billow)
adA__ 8 z80 GPL3 Zilog Z80 (by condret)
EOF
RUN
Expand Down

0 comments on commit dad52b0

Please sign in to comment.