Skip to content

Commit

Permalink
rotw|round.s|rsil|rsqrt0.s|rsr|rsync
Browse files Browse the repository at this point in the history
  • Loading branch information
imbillow committed Nov 25, 2024
1 parent f452976 commit 0ec8737
Show file tree
Hide file tree
Showing 3 changed files with 239 additions and 27 deletions.
203 changes: 186 additions & 17 deletions librz/arch/isa/xtensa/xtensa_il.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,95 @@

#include "xtensa.h"

static const char *sfr_tbl[256] = {
[0] = "lbeg",
[1] = "lend",
[2] = "lcount",
[3] = "sar",
[4] = "br",
[5] = "litbase",
[12] = "scompare1",
[16] = "acclo",
[17] = "acchi",
[32] = "m0",
[33] = "m1",
[34] = "m2",
[35] = "m3",
[72] = "windowbase",
[73] = "windowstart",
[83] = "ptevaddr",
[90] = "rasid",
[91] = "itlbcfg",
[92] = "dtlbcfg",
[95] = "eracess",
[96] = "ibreakenable",
[97] = "memctl",
[99] = "atomctl",
[104] = "ddr",
[106] = "mepc",
[107] = "meps",
[108] = "mesave",
[109] = "mesr",
[110] = "mecr",
[111] = "mevaddr",
[128] = "ibreaka0",
[129] = "ibreaka1",
[144] = "dbreaka0",
[145] = "dbreaka1",
[160] = "dbreakc0",
[161] = "dbreakc1",
[177] = "epc1",
[178] = "epc2",
[179] = "epc3",
[180] = "epc4",
[181] = "epc5",
[182] = "epc6",
[183] = "epc7",
[192] = "depc",
[193] = "eps1",
[194] = "eps2",
[195] = "eps3",
[196] = "eps4",
[197] = "eps5",
[198] = "eps6",
[199] = "eps7",
[209] = "excsave1",
[210] = "excsave2",
[211] = "excsave3",
[212] = "excsave4",
[213] = "excsave5",
[214] = "excsave6",
[215] = "excsave7",
[224] = "cpenable",
[226] = "interrupt",
[227] = "intclear",
[228] = "intenable",
[230] = "ps",
[231] = "vecbase",
[232] = "exccause",
[233] = "debugcause",
[234] = "ccount",
[235] = "prid",
[236] = "icount",
[237] = "icountlevel",
[238] = "excvaddr",
[240] = "ccompare0",
[241] = "ccompare1",
[242] = "ccompare2",
[244] = "misc0",
[245] = "misc1",
[246] = "misc2",
[247] = "misc3",
NULL,
};

static const char *epc_tbl[] = {
NULL, "epc1", "epc2", "epc3", "epc4", "epc5", "epc6", "epc7"
};
static const char *eps_tbl[] = {
NULL, "eps1", "eps2", "eps3", "eps4", "eps5", "eps6", "eps7"
};

#include <rz_il/rz_il_opbuilder_begin.h>

#define FORMAT (ctx->insn->detail->xtensa.format)
Expand All @@ -12,11 +101,64 @@
#define IREG(I) VARG(REGN(I))
#define IREGi(I, i) VARG(cs_reg_name(ctx->handle, (REGI(I) + i)))
#define IMEM(I) ADD(VARG(REGNAME(MEM((I))->base)), S32(MEM((I))->disp))
#define ABS(X) ITE(SGT(X, S32(0)), X, NEG(X))
#define ISFR(I) VARG(sfr_tbl[REGI(I)])
#define IEPC(I) VARG(epc_tbl[I])
#define IEPS(I) VARG(eps_tbl[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);

enum {
PS_INTLEVEL,
PS_EXCM,
PS_UM,
PS_RING,
PS_OWB,
PS_CALLINC,
PS_WOE,
};

typedef struct {
ut32 field;
ut8 offset;
ut8 width;
} RegField;

typedef struct {
RegField tbl[64];
size_t size;
ut8 width;
} RegFieldTbl;

static const RegFieldTbl ps_field_tbl = {
.tbl = {
{ PS_INTLEVEL, 0, 4 },
{ PS_EXCM, 4, 1 },
{ PS_UM, 5, 1 },
{ PS_RING, 6, 2 },
{ PS_OWB, 8, 4 },
{ PS_CALLINC, 16, 2 },
{ PS_WOE, 18, 1 },
},
.size = 7,
.width = 32,
};

static RzILOpPure *reg_field_set(const RegFieldTbl *tbl, ut32 field, RzILOpPure *orig, RzILOpPure *v) {
for (size_t i = 0; i < tbl->size; ++i) {
const RegField *f = tbl->tbl + i;
if (field == f->field) {
return tbl->width == 32
? DEPOSIT32(orig, U32(f->offset), U32(f->width), v)
: DEPOSIT64(orig, U32(f->offset), U32(f->width), v);
}
}
rz_warn_if_reached();
return NULL;
}

static RzAnalysisLiftedILOp op_abs(XtensaContext *ctx) {
return SETG(REGN(0), ABS(IREG(1)));
}
Expand Down Expand Up @@ -947,30 +1089,22 @@ static RzAnalysisLiftedILOp op_retw(XtensaContext *ctx) {
return NOP();
}

static const char *epc_tbl[] = {
NULL, "epc1", "epc2", "epc3", "epc4", "epc5", "epc6", "epc7"
};
#define EPC(I) VARG(epc_tbl[I])
static const char *eps_tbl[] = {
NULL, "eps1", "eps2", "eps3", "eps4", "eps5", "eps6", "eps7"
};
#define EPS(I) VARG(eps_tbl[I])
#define PS_EXCM_CLEAR SETG("ps.excm", UN(4, 0))

static RzAnalysisLiftedILOp op_rfde(XtensaContext *ctx) {
return JMP(ITE(VARG("ndepc"), VARG("depc"), EPC(1)));
return JMP(ITE(VARG("ndepc"), VARG("depc"), IEPC(1)));
}

#define PS_EXCM_CLEAR SETG("ps", reg_field_set(&ps_field_tbl, PS_EXCM, VARG("ps"), U32(0)))

static RzAnalysisLiftedILOp op_rfe(XtensaContext *ctx) {
return SEQ2(
PS_EXCM_CLEAR,
JMP(EPC(1)));
JMP(IEPC(1)));
}

static RzAnalysisLiftedILOp op_rfi(XtensaContext *ctx) {
return SEQ2(
SETG("ps", EPS(IMM(0))),
JMP(EPC(IMM(0))));
SETG("ps", IEPS(IMM(0))),
JMP(IEPC(IMM(0))));
}

static RzAnalysisLiftedILOp op_rfr(XtensaContext *ctx) {
Expand All @@ -981,14 +1115,43 @@ static RzAnalysisLiftedILOp op_rfr(XtensaContext *ctx) {
static RzAnalysisLiftedILOp op_rfwo(XtensaContext *ctx) {
return SEQ2(
PS_EXCM_CLEAR,
JMP(EPC(1)));
JMP(IEPC(1)));
}

// TODO: windowcheck
static RzAnalysisLiftedILOp op_rfwu(XtensaContext *ctx) {
return SEQ2(
PS_EXCM_CLEAR,
JMP(EPC(1)));
JMP(IEPC(1)));
}

// TODO: window
static RzAnalysisLiftedILOp op_rotw(XtensaContext *ctx) {
return NOP();
}

// FIXME: statusflags
static RzAnalysisLiftedILOp op_round_s(XtensaContext *ctx) {
return SETG(REGN(0),
F2BV(FROUND(RZ_FLOAT_RMODE_RNA, FMUL(RZ_FLOAT_RMODE_RNA, FLOATV32(IREG(1)), F32(pow(2, IMM(2)))))));
}

static RzAnalysisLiftedILOp op_rsil(XtensaContext *ctx) {
return SEQ2(SETG(REGN(0), VARG("ps")),
SETG("ps.intlevel", U32(IMM(1))));
}

// FIXME: statusflags+reciprocal_square_root_approximation
static RzAnalysisLiftedILOp op_rsqrt0_s(XtensaContext *ctx) {
return NOP();
}

static RzAnalysisLiftedILOp op_rsr(XtensaContext *ctx) {
return SETG(REGN(0), ISFR(IMM(1)));
}

static RzAnalysisLiftedILOp op_rsync(XtensaContext *ctx) {
return NOP();
}

#include <rz_il/rz_il_opbuilder_end.h>
Expand Down Expand Up @@ -1201,6 +1364,12 @@ static const fn_analyze_op_il fn_tbl[] = {
[XTENSA_INS_RFR] = op_rfr,
[XTENSA_INS_RFWO] = op_rfwo,
[XTENSA_INS_RFWU] = op_rfwu,
[XTENSA_INS_ROTW] = op_rotw,
[XTENSA_INS_ROUND_S] = op_round_s,
[XTENSA_INS_RSIL] = op_rsil,
[XTENSA_INS_RSQRT0_S] = op_rsqrt0_s,
[XTENSA_INS_RSR] = op_rsr,
[XTENSA_INS_RSYNC] = op_rsync,
};

void xtensa_analyze_op_rzil(XtensaContext *ctx, RzAnalysisOp *op) {
Expand Down
57 changes: 50 additions & 7 deletions librz/arch/p/analysis/analysis_xtensa_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ static char *xtensa_get_reg_profile(RzAnalysis *analysis) {
"gpr b14 .1 224 0\n"
"gpr b15 .1 225 0\n"

/*Special Registers*/
/*0*/ "gpr lbeg .32 226 0\n"
/*1*/ "gpr lend .32 230 0\n"
/*2*/ "gpr lcount .32 234 0\n"
Expand All @@ -115,33 +116,75 @@ static char *xtensa_get_reg_profile(RzAnalysis *analysis) {
/*35*/ "gpr m3 .32 366 0\n"
/*72*/ "gpr windowbase .32 514 0\n"
/*73*/ "gpr windowstart .32 518 0\n"
/*83*/ "gpr ptevaddr .32 546 0\n"
/*90*/ "gpr rasid .32 570 0\n"
/*91*/ "gpr itlbcfg .32 574 0\n"
/*92*/ "gpr dtlbcfg .32 578 0\n"
/*95*/ "gpr eracess .32 586 0\n"
/*96*/ "gpr ibreakenable .32 590 0\n"
/*97*/ "gpr memctl .32 594 0\n"
/*99*/ "gpr atomctl .32 602 0\n"
/*104*/ "gpr ddr .32 618 0\n"
/*106*/ "gpr mepc .32 626 0\n"
/*107*/ "gpr meps .32 630 0\n"
/*108*/ "gpr mesave .32 634 0\n"
/*109*/ "gpr mesr .32 638 0\n"
/*110*/ "gpr mecr .32 642 0\n"
/*111*/ "gpr mevaddr .32 646 0\n"
/*128*/ "gpr ibreaka0 .32 690 0\n"
/*129*/ "gpr ibreaka1 .32 694 0\n"
/*144*/ "gpr dbreaka0 .32 738 0\n"
/*145*/ "gpr dbreaka1 .32 742 0\n"
/*160*/ "gpr dbreakc0 .32 786 0\n"
/*161*/ "gpr dbreakc1 .32 790 0\n"
/*177*/ "gpr epc1 .32 934 0\n"
/*178*/ "gpr epc2 .32 938 0\n"
/*179*/ "gpr epc3 .32 942 0\n"
/*180*/ "gpr epc4 .32 946 0\n"
/*181*/ "gpr epc5 .32 950 0\n"
/*182*/ "gpr epc6 .32 954 0\n"
/*183*/ "gpr epc7 .32 958 0\n"
/*192*/ "gpr depc .32 994 0\n"
/*193*/ "gpr eps1 .32 998 0\n"
/*194*/ "gpr eps2 .32 1002 0\n"
/*195*/ "gpr eps3 .32 1006 0\n"
/*196*/ "gpr eps4 .32 1010 0\n"
/*197*/ "gpr eps5 .32 1014 0\n"
/*198*/ "gpr eps6 .32 1018 0\n"
/*199*/ "gpr eps7 .32 1022 0\n"
/*230*/ "gpr ps .32 1066 0\n"
/*209*/ "gpr excsave1 .32 1062 0\n"
/*210*/ "gpr excsave2 .32 1066 0\n"
/*211*/ "gpr excsave3 .32 1070 0\n"
/*212*/ "gpr excsave4 .32 1074 0\n"
/*213*/ "gpr excsave5 .32 1078 0\n"
/*214*/ "gpr excsave6 .32 1082 0\n"
/*215*/ "gpr excsave7 .32 1086 0\n"
/*224*/ "gpr cpenable .32 1122 0\n"
/*226*/ "gpr interrupt .32 1126 0\n"
/*227*/ "gpr intclear .32 1130 0\n"
/*228*/ "gpr intenable .32 1134 0\n"
/*230*/ "gpr ps .32 1138 0\n"
/*231*/ "gpr vecbase .32 1142 0\n"
/*232*/ "gpr exccause .32 1146 0\n"
/*233*/ "gpr debugcause .32 1150 0\n"
/*234*/ "gpr ccount .32 1154 0\n"
/*235*/ "gpr prid .32 1158 0\n"
/*236*/ "gpr icount .32 1162 0\n"
/*237*/ "gpr icountlevel .32 1166 0\n"
/*238*/ "gpr excvaddr .32 1170 0\n"
/*240*/ "gpr ccompare0 .32 1178 0\n"
/*241*/ "gpr ccompare1 .32 1182 0\n"
/*242*/ "gpr ccompare2 .32 1186 0\n"
/*244*/ "gpr misc0 .32 1190 0\n"
/*245*/ "gpr misc1 .32 1194 0\n"
/*246*/ "gpr misc2 .32 1198 0\n"
/*247*/ "gpr misc3 .32 1202 0\n"

"gpr ndepc .1 2000 0\n"
"gpr ResetVector .32 2004 0\n"
"gpr UserExceptionVector .32 2008 0\n"
"gpr KernelExceptionVector .32 2012 0\n"
"gpr DoubleExceptionVector .32 2016 0\n"
"gpr exccause .6 2104 0\n"
"gpr excsave .32 2108 0\n"
"gpr ps.excm .4 2112 0\n"
"gpr ps.um .1 2116 0\n"
"gpr excvaddr .32 2120 0\n"
"gpr depc .32 2124 0\n"

// pc
"gpr pc .32 68 0\n"
Expand Down
6 changes: 3 additions & 3 deletions test/db/asm/xtensa
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,8 @@ d "ret.n" 0df0 0x0 (jmp (var a0))
d "retw" 900000 0x0 nop
d "retw.n" 1df0 0x0 nop
d "rfde" 003200 0x0 (jmp (ite (var ndepc) (var depc) (var epc1)))
d "rfe" 003000 0x0 (seq (set ps.excm (bv 4 0x0)) (jmp (var epc1)))
d "rfe" 003000 0x0 (seq (set ps (| (& (var ps) (~ (<< (>> (bv 32 0xffffffff) (- (bv 32 0x20) (bv 32 0x1)) false) (bv 32 0x4) false))) (& (<< (bv 32 0x0) (bv 32 0x4) false) (<< (>> (bv 32 0xffffffff) (- (bv 32 0x20) (bv 32 0x1)) false) (bv 32 0x4) false)))) (jmp (var epc1)))
d "rfi 2" 103200 0x0 (seq (set ps (var eps2)) (jmp (var epc2)))
d "rfr a1, f2" 4012fa 0x0 (set a1 (cast 32 false (var f2)))
d "rfwo" 003400 0x0 (seq (set ps.excm (bv 4 0x0)) (jmp (var epc1)))
d "rfwu" 003500 0x0 (seq (set ps.excm (bv 4 0x0)) (jmp (var epc1)))
d "rfwo" 003400 0x0 (seq (set ps (| (& (var ps) (~ (<< (>> (bv 32 0xffffffff) (- (bv 32 0x20) (bv 32 0x1)) false) (bv 32 0x4) false))) (& (<< (bv 32 0x0) (bv 32 0x4) false) (<< (>> (bv 32 0xffffffff) (- (bv 32 0x20) (bv 32 0x1)) false) (bv 32 0x4) false)))) (jmp (var epc1)))
d "rfwu" 003500 0x0 (seq (set ps (| (& (var ps) (~ (<< (>> (bv 32 0xffffffff) (- (bv 32 0x20) (bv 32 0x1)) false) (bv 32 0x4) false))) (& (<< (bv 32 0x0) (bv 32 0x4) false) (<< (>> (bv 32 0xffffffff) (- (bv 32 0x20) (bv 32 0x1)) false) (bv 32 0x4) false)))) (jmp (var epc1)))

0 comments on commit 0ec8737

Please sign in to comment.