diff --git a/librz/analysis/arch/v810/v810.h b/librz/analysis/arch/v810/v810.h new file mode 100644 index 00000000000..9cab2ea8182 --- /dev/null +++ b/librz/analysis/arch/v810/v810.h @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: 2024 billow +// SPDX-License-Identifier: LGPL-3.0-only + +#ifndef RIZIN_V810_H +#define RIZIN_V810_H + +#include +#include + +enum { + C_BGT = 0b1111, + C_BGE = 0b1110, + C_BLT = 0b0110, + C_BLE = 0b0111, + + C_BH = 0b1011, + C_BNL = 0b1001, + C_BL = 0b0001, + C_BNH = 0b0011, + + C_BE = 0b0010, + C_BNE = 0b1010, + + C_BV = 0b000, + C_BNV = 0b1000, + C_BN = 0b0100, + C_BP = 0b1100, + C_BC = 0b0001, + C_BNC = 0b1001, + C_BZ = 0b0010, + C_BNZ = 0b1010, + C_BR = 0b0101, + C_NOP = 0b1101, +}; + +typedef struct { + RzAnalysis *a; + ut16 w1; + ut16 w2; + ut32 pc; +} V810AnalysisContext; + +RzAnalysisILConfig *v810_il_config(RzAnalysis *a); +RzAnalysisLiftedILOp v810_il_op(const V810AnalysisContext *a); + +#endif // RIZIN_V810_H diff --git a/librz/analysis/arch/v810/v810_il.c b/librz/analysis/arch/v810/v810_il.c new file mode 100644 index 00000000000..8c7b0b8a20c --- /dev/null +++ b/librz/analysis/arch/v810/v810_il.c @@ -0,0 +1,684 @@ +// SPDX-FileCopyrightText: 2024 billow +// SPDX-License-Identifier: LGPL-3.0-only + +#include "v810.h" +#include + +static const char *registers[] = { + "r0", + "r1", + "r2", + "r3", + "r4", + "r5", + "r6", + "r7", + "r8", + "r9", + "r10", + "r11", + "r12", + "r13", + "r14", + "r15", + "r16", + "r17", + "r18", + "r19", + "r20", + "r21", + "r22", + "r23", + "r24", + "r25", + "r26", + "r27", + "r28", + "r29", + "r30", + "r31", + "EIPC", + "EIPSW", + "FEPC", + "FEPSW", + "ECR", + "PSW", + "PIR", + "TKCW", + "Reserved_8", + "Reserved_9", + "Reserved_10", + "Reserved_11", + "Reserved_12", + "Reserved_13", + "Reserved_14", + "Reserved_15", + "Reserved_16", + "Reserved_17", + "Reserved_18", + "Reserved_19", + "Reserved_20", + "Reserved_21", + "Reserved_22", + "Reserved_23", + "CHCW", + "ADTRE", + "Reserved_26", + "Reserved_27", + "Reserved_28", + "Reserved_29", + "Reserved_30", + "Reserved_31", + NULL +}; + +static const char *GR[] = { + "r0", + "r1", + "r2", + "r3", + "r4", + "r5", + "r6", + "r7", + "r8", + "r9", + "r10", + "r11", + "r12", + "r13", + "r14", + "r15", + "r16", + "r17", + "r18", + "r19", + "r20", + "r21", + "r22", + "r23", + "r24", + "r25", + "r26", + "r27", + "r28", + "r29", + "r30", + "r31", + NULL +}; + +static const char **SR = registers + 32; + +RzAnalysisILConfig *v810_il_config(RzAnalysis *a) { + rz_return_val_if_fail(a, NULL); + assert(RZ_STR_EQ(SR[0], "EIPC")); + + RzAnalysisILConfig *cfg = rz_analysis_il_config_new(32, false, 32); + cfg->reg_bindings = registers; + return cfg; +} + +static inline int32_t sext32(uint32_t X, unsigned B) { + rz_warn_if_fail(B > 0 && B <= 32); + return (int32_t)(X << (32 - B)) >> (32 - B); +} + +#define COPCODE ((ctx->w1 >> 10) & 0x3F) +#define R1 (GR[((ctx->w1) & 0x1F)]) +#define R2 (GR[(((ctx->w1) >> 5) & 0x1F)]) +#define I5 REG1((ctx->w1)) +#define I9 (ctx->w1 & 0X1FF) +#define I16 (ctx->w2) +#define I26 (ctx->w2 | ((ctx->w1 & 0x3ff) << 16)) +#define CCOND (((ctx->w1) >> 9) & 0xF) +#define SUBOPC (((ctx->w2) >> 10) & 0x3F) + +#define R1V VARG(R1) +#define R2V VARG(R2) +#define SEXT5 S32(sext32(I5, 5)) +#define SEXT9 S32(sext32(I9, 9)) +#define SEXT16 S32(sext32(I16, 16)) +#define SEXT26 S32(sext32(I26, 26)) +#define ZEXT5 U32(I5) +#define ZEXT9 U32(I9) +#define ZEXT16 U32(I16) +#define ZEXT26 U32(I26) + +#define R1F FLOATV32(VARG(R1)) +#define R2F FLOATV32(VARG(R2)) + +static RzILOpPure *shl0(RzILOpPure *a, RzILOpPure *b) { + return SHIFTL0(a, b); +} + +static RzILOpPure *shr0(RzILOpPure *a, RzILOpPure *b) { + return SHIFTR0(a, b); +} + +static RzILOpPure *fadd_(RzILOpPure *a, RzILOpPure *b) { + return FADD(0, a, b); +} + +static RzILOpPure *fsub_(RzILOpPure *a, RzILOpPure *b) { + return FSUB(0, a, b); +} + +static RzILOpPure *fmul_(RzILOpPure *a, RzILOpPure *b) { + return FMUL(0, a, b); +} + +static RzILOpPure *fdiv_(RzILOpPure *a, RzILOpPure *b) { + return FSUB(0, a, b); +} + +static RzILOpPure *bv2f32(RzILOpPure *x) { + return FLOATV32(x); +} + +static RzILOpPure *f32_2int(RzILOpPure *x) { + return F2SINT(32, 0, x); +} + +static RzILOpPure *f32_trunc2int(RzILOpPure *x) { + return F2SINT(32, 0, FROUND(0, x)); +} + +typedef struct { + const char *p; + const char *x; + unsigned i; + unsigned b; +} FLG; + +static const FLG flags[] = { + { "PSW", "RFU", 20, 12 }, + { "PSW", "I3", 19, 1 }, + { "PSW", "I2", 18, 1 }, + { "PSW", "I1", 17, 1 }, + { "PSW", "I0", 16, 1 }, + { "PSW", "NP", 15, 1 }, + { "PSW", "EP", 14, 1 }, + { "PSW", "AE", 13, 1 }, + { "PSW", "ID", 12, 1 }, + { "PSW", "RFU", 10, 2 }, + { "PSW", "FRO", 9, 1 }, + { "PSW", "FIV", 8, 1 }, + { "PSW", "FZD", 7, 1 }, + { "PSW", "FOV", 6, 1 }, + { "PSW", "FUD", 5, 1 }, + { "PSW", "FPR", 4, 1 }, + { "PSW", "CY", 3, 1 }, + { "PSW", "OV", 2, 1 }, + { "PSW", "S", 1, 1 }, + { "PSW", "Z", 0, 1 }, + + { "PIR", "RFU", 16, 16 }, + { "PIR", "PT", 4, 12 }, + { "PIR", "NECRV", 0, 4 }, + + { "TKCW", "RFU", 9, 24 }, + { "TKCW", "OTM", 8, 1 }, + { "TKCW", "FIT", 7, 1 }, + { "TKCW", "FZT", 6, 1 }, + { "TKCW", "FVT", 5, 1 }, + { "TKCW", "FUT", 4, 1 }, + { "TKCW", "FPT", 3, 1 }, + { "TKCW", "RDI", 2, 1 }, + { "TKCW", "RD", 0, 2 }, + + { "CHCW", "SA", 8, 25 }, + { "CHCW", "CEN", 20, 12 }, + { "CHCW", "CEC", 8, 12 }, + { "CHCW", "RFU", 6, 2 }, + { "CHCW", "ICR", 5, 1 }, + { "CHCW", "ICD", 4, 1 }, + { "CHCW", "RFU", 2, 2 }, + { "CHCW", "ICE", 1, 1 }, + { "CHCW", "ICC", 0, 1 }, +}; + +static const FLG *flag_find(const char *p, const char *x) { + for (int i = 0; i < RZ_ARRAY_SIZE(flags); ++i) { + const FLG *f = flags + i; + if (RZ_STR_NE(p, f->p)) { + continue; + } + if (RZ_STR_NE(x, f->x)) { + continue; + } + return f; + } + return NULL; +} + +static RzILOpPure *VARGb(const char *p, const char *x) { + const FLG *f = flag_find(p, x); + if (!f) { + rz_warn_if_reached(); + return NULL; + } + RzILOpPure *y = LET("_v_parent", VARG(p), + LOGAND(shr0(VARLP("_v_parent"), U32(f->i)), U32(f->b))); + if (f->b == 1) { + y = LET("_v_part", y, + NON_ZERO(VARLP("_v_part"))); + } + return y; +} + +static RzILOpEffect *SETGbs(const char *p, unsigned n, ...) { + va_list args; + va_start(args, n); + + RzILOpPure *expr = NULL; + for (unsigned i = 0; i < n; ++i) { + const char *x = va_arg(args, const char *); + RzILOpPure *y = va_arg(args, RzILOpPure *); + + const FLG *f = flag_find(p, x); + if (!f) { + rz_warn_if_reached(); + return NULL; + } + + RzILOpPure *v = shl0(f->b == 1 ? BOOL_TO_BV(y, 32) : y, U32(f->i)); + expr = !expr ? v : LOGOR(expr, v); + } + return SETG(p, expr); +} + +#define SETGb(p, ...) SETGbs(p, 1, __VA_ARGS__) + +static RzILOpPure *overflow(RzILOpPure *x) { + return LET("_x", x, + OR( + SGT(VARLP("_x"), S32(+0x7fffffff)), + SLT(VARLP("_x"), S32(-0x80000000)))); +} + +static RzAnalysisLiftedILOp flags_update(const V810AnalysisContext *ctx) { + switch (COPCODE) { + case V810_NOT: + case V810_DIVU: + case V810_AND: + case V810_OR: + case V810_ORI: + case V810_XOR: + case V810_XORI: + return SETGbs("PSW", 3, + "OV", IL_FALSE, + "S", SLT(R2V, S32(0)), + "Z", IS_ZERO(R2V)); + case V810_ANDI: + return SETGbs("PSW", 3, + "OV", IL_FALSE, + "S", IL_FALSE, + "Z", IS_ZERO(R2V)); + + case V810_DIV: + case V810_MUL: + case V810_MULU: + return SETGbs("PSW", 3, + "OV", overflow(R2V), + "S", SLT(R2V, S32(0)), + "Z", IS_ZERO(R2V)); + + case V810_CMP_IMM5: + return SETGbs("PSW", 4, + "CY", SLT(R2V, SEXT5), + "OV", overflow(VARL("result")), + "S", SLT(VARL("result"), S32(0)), + "Z", IS_ZERO(VARL("result"))); + case V810_CMP: + case V810_SUB: + return SETGbs("PSW", 4, + "CY", SLT(R2V, R1V), + "OV", overflow(VARL("result")), + "S", SLT(VARL("result"), S32(0)), + "Z", IS_ZERO(VARL("result"))); + case V810_ADD: + return SETGbs("PSW", 4, + "CY", OR(SLT(VARL("result"), R2V), SLT(VARL("result"), R1V)), + "OV", overflow(VARL("result")), + "S", SLT(VARL("result"), S32(0)), + "Z", IS_ZERO(VARL("result"))); + case V810_ADD_IMM5: + return SETGbs("PSW", 4, + "CY", OR(SLT(VARL("result"), R2V), SLT(VARL("result"), SEXT5)), + "OV", overflow(VARL("result")), + "S", SLT(VARL("result"), S32(0)), + "Z", IS_ZERO(VARL("result"))); + case V810_ADDI: + return SETGbs("PSW", 4, + "CY", OR(SLT(VARL("result"), SEXT16), SLT(VARL("result"), R1V)), + "OV", overflow(VARL("result")), + "S", SLT(VARL("result"), S32(0)), + "Z", IS_ZERO(VARL("result"))); + case V810_SAR: + case V810_SHR: + return SETGbs("PSW", 3, + "CY", AND(NON_ZERO(ZEXT5), NON_ZERO(LOGAND(R2V, SUB(shl0(U32(1), ZEXT5), U32(1))))), + "S", SLT(VARL("result"), S32(0)), + "Z", IS_ZERO(VARL("result"))); + case V810_SAR_IMM5: + case V810_SHR_IMM5: + return SETGbs("PSW", 3, + "CY", AND(NON_ZERO(R1V), NON_ZERO(LOGAND(R2V, SUB(shl0(U32(1), R1V), U32(1))))), + "S", SLT(VARL("result"), S32(0)), + "Z", IS_ZERO(VARL("result"))); + + case V810_SHL: + return SETGbs("PSW", 3, + "CY", AND(NON_ZERO(ZEXT5), NON_ZERO(shr0(R2V, SUB(U32(32), R1V)))), + "S", SLT(VARL("result"), S32(0)), + "Z", IS_ZERO(VARL("result"))); + case V810_SHL_IMM5: + return SETGbs("PSW", 3, + "CY", AND(NON_ZERO(ZEXT5), NON_ZERO(shr0(R2V, SUB(U32(32), ZEXT5)))), + "S", SLT(VARL("result"), S32(0)), + "Z", IS_ZERO(VARL("result"))); + case V810_CAXI: + return SETGbs("PSW", 4, + "CY", SLT(R2V, R1V), + "OV", overflow(VARL("result")), + "S", SLT(VARL("result"), S32(0)), + "Z", IS_ZERO(VARL("result"))); + case V810_EXT: { + switch (SUBOPC) { + case V810_EXT_CMPF_S: return SETGbs("PSW", 4, + "OV", IL_FALSE, + "S", SLT(VARL("result"), S32(0)), + "Z", IS_ZERO(VARL("result")), + "FRO", LET("_x", R2F, OR(IS_FNAN(VARLP("_x")), IS_FINF(VARLP("_x")))) // TODO: denormal number + // "FPR", // 1 if degradation in precision is detected; otherwise, not affected + ); + case V810_EXT_CVT_WS: return SETGbs("PSW", 5, + "CY", INV(IS_FPOS(R2F)), + "OV", IL_FALSE, + "S", FLT(R2F, F32(0)), + "Z", IS_ZERO(R2F), + "FRO", LET("_x", R2F, OR(IS_FNAN(VARLP("_x")), IS_FINF(VARLP("_x")))) // TODO: denormal number + // "FPR", // TODO: 1 if degradation in precision is detected; otherwise, not affected + ); + case V810_EXT_CVT_SW: return SETGbs("PSW", 3, + "OV", IL_FALSE, + "S", SLT(R2V, S32(0)), + "Z", IS_ZERO(R2V) + // "FRO", LET("_x", R2V, OR(IS_FNAN(VARLP("_x")), IS_FINF(VARLP("_x")))) // TODO: denormal number + // ,"FIV",// TODO: invalid operation occurs + // "FPR", // TODO: 1 if degradation in precision is detected; otherwise, not affected + ); + case V810_EXT_ADDF_S: + case V810_EXT_SUBF_S: + case V810_EXT_MULF_S: + case V810_EXT_DIVF_S: return SETGbs("PSW", 6, + "CY", INV(IS_FPOS(VARL("result"))), + "OV", IL_FALSE, + "S", FLT(VARL("result"), F32(0)), + "Z", IS_FZERO(VARL("result")), + "FRO", OR(IS_FNAN(VARL("result")), IS_FINF(VARL("result"))) // TODO: denormal number + // ,"FIV",// TODO: invalid operation occurs + , + "FZD", IS_FZERO(R1F) + // "FOV", // TODO: 1 if result of operation is greater than maximum normalized number that can be expressed; + // "FUD", // TODO: if result of operation is less than minimum (absolute value) normalized number that can be expressed; + // "FPR", // TODO: 1 if degradation in precision is detected; otherwise, not affected + ); + case V810_EXT_XB: + case V810_EXT_XH: + case V810_EXT_REV: return NOP(); + case V810_EXT_TRNC_SW: return SETGbs("PSW", 4, + "OV", IL_FALSE, + "S", FLT(FLOATV32(VARL("result")), F32(0)), + "Z", IS_FZERO(FLOATV32(VARL("result"))), + "FRO", LET("_x", FLOATV32(VARL("result")), OR(IS_FNAN(VARLP("_x")), IS_FINF(VARLP("_x")))) // TODO: denormal number + // ,"FIV",// TODO: invalid operation occurs + // "FPR", // TODO: 1 if degradation in precision is detected; otherwise, not affected + ); + case V810_EXT_MPYHW: + default: + return NOP(); + } + } + default: + return NOP(); + } +} + +typedef RzILOpPure *(*F_OP1)(RzILOpPure *); +typedef RzILOpPure *(*F_OP2)(RzILOpPure *, RzILOpPure *); + +static RzAnalysisLiftedILOp lift_mov(const V810AnalysisContext *ctx, RzILOpPure *x0) { + return SETG(R2, x0); +} + +static RzAnalysisLiftedILOp lift_op1(const V810AnalysisContext *ctx, RzILOpPure *x0, F_OP1 f) { + return SEQ2( + SETG(R2, f(x0)), + flags_update(ctx)); +} + +static RzAnalysisLiftedILOp lift_op2(const V810AnalysisContext *ctx, RzILOpPure *x0, RzILOpPure *x1, F_OP2 f) { + return SEQ3( + SETL("result", f(x0, x1)), + flags_update(ctx), + SETG(R2, VARL("result"))); +} + +static RzAnalysisLiftedILOp lift_fop1(const V810AnalysisContext *ctx, RzILOpPure *x0, F_OP1 f) { + return SEQ2( + SETG(R2, F2BV(f(x0))), + flags_update(ctx)); +} + +static RzAnalysisLiftedILOp lift_fop2(const V810AnalysisContext *ctx, RzILOpPure *x0, RzILOpPure *x1, F_OP2 f) { + return SEQ3( + SETL("result", f(x0, x1)), + flags_update(ctx), + SETG(R2, F2BV(VARL("result")))); +} + +static RzAnalysisLiftedILOp lift_div(const V810AnalysisContext *ctx, RzILOpPure *x0, RzILOpPure *x1) { + return SEQ3( + SETG(R2, DIV(x0, x1)), + SETG(GR[30], MOD(DUP(x0), DUP(x1))), + flags_update(ctx)); +} + +static RzAnalysisLiftedILOp lift_mul(const V810AnalysisContext *ctx, RzILOpPure *x0, RzILOpPure *x1) { + return SEQ4( + SETL("result", MUL(SIGNED(64, x0), SIGNED(64, x1))), + SETG(R2, UNSIGNED(32, VARL("result"))), + SETG(GR[30], UNSIGNED(32, shr0(VARL("result"), U32(32)))), + flags_update(ctx)); +} + +static RzAnalysisLiftedILOp lift_mulu(const V810AnalysisContext *ctx, RzILOpPure *x0, RzILOpPure *x1) { + return SEQ4( + SETL("result", MUL(UNSIGNED(64, x0), UNSIGNED(64, x1))), + SETG(R2, UNSIGNED(32, VARL("result"))), + SETG(GR[30], UNSIGNED(32, shr0(VARL("result"), U32(32)))), + flags_update(ctx)); +} + +static RzAnalysisLiftedILOp lift_cmp(const V810AnalysisContext *ctx, RzILOpPure *x0, RzILOpPure *x1, F_OP2 f) { + return SEQ2( + SETL("result", f(x0, x1)), + flags_update(ctx)); +} + +static RzAnalysisLiftedILOp lift_ld(const V810AnalysisContext *ctx, RzILOpPure *addr, unsigned B) { + RzILOpPure *y = LOADW(B, VARL("_adr")); + if (B == 8 || B == 16) { + y = LET("_v", UNSIGNED(32, y), SEXTRACT32(VARLP("_v"), U32(0), U32(B))); + } else { + rz_warn_if_fail(B == 32); + } + return SEQ2( + SETL("_adr", addr), + SETG(R2, y)); +} + +static RzAnalysisLiftedILOp lift_st(const V810AnalysisContext *ctx, RzILOpPure *addr, unsigned B) { + RzILOpPure *y = R2V; + if (B == 8 || B == 16) { + y = UNSIGNED(B, y); + } else { + rz_warn_if_fail(B == 32); + } + return SEQ2( + SETL("_adr", addr), + STOREW(VARL("_adr"), y)); +} + +static RzAnalysisLiftedILOp lift_reti(const V810AnalysisContext *ctx) { + return SEQ3( + SETL("_pc", ITE(VARGb("PSW", "NP"), VARG("FEPC"), VARG("EIPC"))), + SETL("PSW", ITE(VARGb("PSW", "NP"), VARG("FEPSW"), VARG("EIPSW"))), + JMP(VARL("_pc"))); +} + +static RzAnalysisLiftedILOp lift_jal(const V810AnalysisContext *ctx) { + return SEQ3( + SETG(GR[31], ADD(U32(ctx->pc), U32(4))), + SETL("_pc", ADD(U32(ctx->pc), SEXT26)), + JMP(VARL("_pc"))); +} + +static RzAnalysisLiftedILOp lift_jr(const V810AnalysisContext *ctx) { + return SEQ2( + SETL("_pc", ADD(S32(ctx->pc), SEXT26)), + JMP(VARL("_pc"))); +} + +static RzAnalysisLiftedILOp lift_caxi(const V810AnalysisContext *ctx) { + return SEQ5( + SETL("_adr", ADD(R1V, SEXT16)), + SETL("_tmp", LOADW(32, VARL("_adr"))), + SETL("result", SUB(R2V, VARL("_tmp"))), + flags_update(ctx), + BRANCH(IS_ZERO(VARL("result")), + SEQ2( + STOREW(VARL("_adr"), VARG(GR[30])), + SETG(R2, VARL("_tmp"))), + SEQ2( + STOREW(VARL("_adr"), VARL("_tmp")), + SETG(R2, VARL("_tmp"))))); +} + +static RzAnalysisLiftedILOp lift_bcond(const V810AnalysisContext *ctx, RzILOpPure *cond) { + return BRANCH(cond, SEQ2(SETL("_pc", ADD(S32(ctx->pc), SEXT9)), JMP(VARL("_pc"))), NOP()); +} + +RzAnalysisLiftedILOp v810_il_op(const V810AnalysisContext *ctx) { + switch (COPCODE) { + case V810_MOV: return lift_mov(ctx, R1V); + case V810_MOV_IMM5: return lift_mov(ctx, SEXT5); + case V810_MOVHI: return lift_mov(ctx, ADD(R1V, shl0(ZEXT16, U32(16)))); + case V810_MOVEA: return lift_mov(ctx, ADD(R1V, SEXT16)); + case V810_LDSR: return SETG(SR[I5], R2V); + case V810_STSR: return SETG(R2, VARG(SR[I5])); + case V810_NOT: return lift_op1(ctx, R1V, rz_il_op_new_log_not); + case V810_DIV: + case V810_DIVU: return lift_div(ctx, R2V, R1V); + case V810_OR: return lift_op2(ctx, R2V, R1V, rz_il_op_new_log_or); + case V810_ORI: return lift_op2(ctx, R2V, ZEXT16, rz_il_op_new_log_or); + case V810_MUL: return lift_mul(ctx, R2V, R1V); + case V810_MULU: return lift_mulu(ctx, R2V, R1V); + case V810_XOR: return lift_op2(ctx, R2V, R1V, rz_il_op_new_log_xor); + case V810_XORI: return lift_op2(ctx, R2V, ZEXT16, rz_il_op_new_log_xor); + case V810_AND: return lift_op2(ctx, R2V, R1V, rz_il_op_new_log_and); + case V810_ANDI: return lift_op2(ctx, R2V, ZEXT16, rz_il_op_new_log_and); + case V810_CMP: return lift_cmp(ctx, R2V, R1V, rz_il_op_new_sub); + case V810_CMP_IMM5: return lift_cmp(ctx, R2V, SEXT5, rz_il_op_new_sub); + case V810_SUB: return lift_op2(ctx, R2V, R1V, rz_il_op_new_sub); + case V810_ADD: return lift_op2(ctx, R2V, R1V, rz_il_op_new_add); + case V810_ADDI: return lift_op2(ctx, R1V, SEXT16, rz_il_op_new_add); + case V810_ADD_IMM5: return lift_op2(ctx, R2V, SEXT5, rz_il_op_new_add); + case V810_SHR: return lift_op2(ctx, R2V, R1V, shr0); + case V810_SHR_IMM5: return lift_op2(ctx, R2V, ZEXT5, shr0); + case V810_SAR: return lift_op2(ctx, R2V, R1V, rz_il_op_new_shiftr_arith); + case V810_SAR_IMM5: return lift_op2(ctx, R2V, ZEXT5, rz_il_op_new_shiftr_arith); + case V810_SHL: return lift_op2(ctx, R2V, R1V, shl0); + case V810_SHL_IMM5: return lift_op2(ctx, R2V, ZEXT5, shl0); + + case V810_INB: + case V810_LDB: return lift_ld(ctx, ADD(R1V, SEXT16), 8); + case V810_INH: + case V810_LDH: return lift_ld(ctx, ADD(R1V, SEXT16), 16); + case V810_INW: + case V810_LDW: return lift_ld(ctx, ADD(R1V, SEXT16), 32); + + case V810_OUTB: + case V810_STB: return lift_st(ctx, ADD(R1V, SEXT16), 8); + case V810_OUTH: + case V810_STH: return lift_st(ctx, ADD(R1V, SEXT16), 16); + case V810_OUTW: + case V810_STW: return lift_st(ctx, ADD(R1V, SEXT16), 32); + + case V810_HALT: + case V810_TRAP: return NOP(); + case V810_RETI: return lift_reti(ctx); + case V810_JMP: return JMP(LOGAND(R1V, U32(0xfffffffe))); + case V810_JAL: return lift_jal(ctx); + case V810_JR: return lift_jr(ctx); + case V810_CLI: + case V810_SEI: return NOP(); + case V810_CAXI: return lift_caxi(ctx); + case V810_EXT: { + switch (SUBOPC) { + case V810_EXT_CMPF_S: return lift_cmp(ctx, R2F, R1F, fsub_); + case V810_EXT_CVT_WS: return lift_fop1(ctx, R1V, bv2f32); + case V810_EXT_CVT_SW: return lift_op1(ctx, R1F, f32_2int); + case V810_EXT_ADDF_S: return lift_fop2(ctx, R2F, R1F, fadd_); + case V810_EXT_SUBF_S: return lift_fop2(ctx, R2F, R1F, fsub_); + case V810_EXT_MULF_S: return lift_fop2(ctx, R2F, R1F, fmul_); + case V810_EXT_DIVF_S: return lift_fop2(ctx, R2F, R1F, fdiv_); + case V810_EXT_XB: + case V810_EXT_XH: + case V810_EXT_REV: return NOP(); + case V810_EXT_TRNC_SW: return lift_fop1(ctx, R1V, f32_trunc2int); + case V810_EXT_MPYHW: return NOP(); + default: break; + } + break; + } + default: + if (COPCODE >> 3 == 4) { + RzILOpPure *cnd = NULL; + switch (CCOND) { + case C_BGT: cnd = INV(OR(XOR(VARGb("PSW", "S"), VARGb("PSW", "OV")), VARGb("PSW", "Z"))); break; + case C_BGE: cnd = INV(XOR(VARGb("PSW", "S"), VARGb("PSW", "OV"))); break; + case C_BLT: cnd = XOR(VARGb("PSW", "S"), VARGb("PSW", "OV")); break; + case C_BLE: cnd = OR(XOR(VARGb("PSW", "S"), VARGb("PSW", "OV")), VARGb("PSW", "Z")); break; + + case C_BH: cnd = INV(OR(VARGb("PSW", "CY"), VARGb("PSW", "Z"))); break; + case C_BNL: cnd = INV(VARGb("PSW", "CY")); break; + case C_BL: cnd = VARGb("PSW", "CY"); break; + case C_BNH: cnd = OR(VARGb("PSW", "CY"), VARGb("PSW", "Z")); break; + + case C_BE: cnd = VARGb("PSW", "Z"); break; + case C_BNE: cnd = INV(VARGb("PSW", "Z")); break; + + case C_BV: cnd = VARGb("PSW", "OV"); break; + case C_BNV: cnd = INV(VARGb("PSW", "OV")); break; + case C_BN: cnd = VARGb("PSW", "S"); break; + case C_BP: cnd = INV(VARGb("PSW", "S")); break; + // case C_BC: break; + // case C_BNC: break; + // case C_BZ: break; + // case C_BNZ: break; + case C_BR: cnd = IL_TRUE; break; + case C_NOP: cnd = IL_FALSE; break; + default: break; + } + return lift_bcond(ctx, cnd); + } + break; + } + rz_warn_if_reached(); + return NULL; +} + +#include diff --git a/librz/analysis/meson.build b/librz/analysis/meson.build index 5176fb314bf..441b7efaa22 100644 --- a/librz/analysis/meson.build +++ b/librz/analysis/meson.build @@ -170,6 +170,7 @@ rz_analysis_sources = [ 'arch/x86/x86_il.c', 'arch/8051/8051_il.c', 'arch/8051/8051_parse.c', + 'arch/v810/v810_il.c', '../asm/arch/amd29k/amd29k.c', '../asm/arch/avr/disassembler.c', '../asm/arch/cil/cil_dis.c', diff --git a/librz/analysis/p/analysis_v810.c b/librz/analysis/p/analysis_v810.c index 596bce34b4b..36105e4cddb 100644 --- a/librz/analysis/p/analysis_v810.c +++ b/librz/analysis/p/analysis_v810.c @@ -8,7 +8,7 @@ #include #include -#include +#include "../arch/v810/v810.h" enum { V810_FLAG_CY = 1, @@ -17,277 +17,213 @@ enum { V810_FLAG_Z = 8, }; -static void update_flags(RzAnalysisOp *op, int flags) { +static void update_flags(RzStrBuf *out, int flags) { if (flags & V810_FLAG_CY) { - rz_strbuf_append(&op->esil, ",31,$c,cy,:="); + rz_strbuf_append(out, ",31,$c,cy,:="); } if (flags & V810_FLAG_OV) { - rz_strbuf_append(&op->esil, ",31,$o,ov,:="); + rz_strbuf_append(out, ",31,$o,ov,:="); } if (flags & V810_FLAG_S) { - rz_strbuf_append(&op->esil, ",31,$s,s,:="); + rz_strbuf_append(out, ",31,$s,s,:="); } if (flags & V810_FLAG_Z) { - rz_strbuf_append(&op->esil, ",$z,z,:="); + rz_strbuf_append(out, ",$z,z,:="); } } -static void clear_flags(RzAnalysisOp *op, int flags) { +static void clear_flags(RzStrBuf *out, int flags) { if (flags & V810_FLAG_CY) { - rz_strbuf_append(&op->esil, ",0,cy,:="); + rz_strbuf_append(out, ",0,cy,:="); } if (flags & V810_FLAG_OV) { - rz_strbuf_append(&op->esil, ",0,ov,:="); + rz_strbuf_append(out, ",0,ov,:="); } if (flags & V810_FLAG_S) { - rz_strbuf_append(&op->esil, ",0,s,:="); + rz_strbuf_append(out, ",0,s,:="); } if (flags & V810_FLAG_Z) { - rz_strbuf_append(&op->esil, ",0,z,:="); + rz_strbuf_append(out, ",0,z,:="); } } -static int v810_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask) { - int ret; - ut8 opcode, reg1, reg2, imm5, cond; - ut16 word1, word2 = 0; - st32 jumpdisp; - struct v810_cmd cmd; - - memset(&cmd, 0, sizeof(cmd)); - - ret = op->size = v810_decode_command(buf, len, &cmd); - if (ret <= 0) { - return ret; - } - - word1 = rz_read_ble16(buf, analysis->big_endian); - - if (ret == 4) { - word2 = rz_read_ble16(buf + 2, analysis->big_endian); - } - - op->addr = addr; - - opcode = OPCODE(word1); - if (opcode >> 3 == 0x4) { - opcode &= 0x20; - } - +static void v810_esil(RzStrBuf *out, ut8 opcode, ut16 word1, ut16 word2) { + ut8 reg1 = 0, reg2 = 0, imm5 = 0, cond = 0; switch (opcode) { case V810_MOV: - op->type = RZ_ANALYSIS_OP_TYPE_MOV; - rz_strbuf_appendf(&op->esil, "r%u,r%u,=", + rz_strbuf_appendf(out, "r%u,r%u,=", REG1(word1), REG2(word1)); break; case V810_MOV_IMM5: - op->type = RZ_ANALYSIS_OP_TYPE_MOV; - rz_strbuf_appendf(&op->esil, "%d,r%u,=", + rz_strbuf_appendf(out, "%d,r%u,=", (st8)SIGN_EXT_T5(IMM5(word1)), REG2(word1)); break; case V810_MOVHI: - op->type = RZ_ANALYSIS_OP_TYPE_MOV; - rz_strbuf_appendf(&op->esil, "16,%hu,<<,r%u,+,r%u,=", + rz_strbuf_appendf(out, "16,%hu,<<,r%u,+,r%u,=", word2, REG1(word1), REG2(word1)); break; case V810_MOVEA: - op->type = RZ_ANALYSIS_OP_TYPE_MOV; - rz_strbuf_appendf(&op->esil, "%hd,r%u,+,r%u,=", + rz_strbuf_appendf(out, "%hd,r%u,+,r%u,=", word2, REG1(word1), REG2(word1)); break; case V810_LDSR: - op->type = RZ_ANALYSIS_OP_TYPE_MOV; - break; case V810_STSR: - op->type = RZ_ANALYSIS_OP_TYPE_MOV; break; case V810_NOT: - op->type = RZ_ANALYSIS_OP_TYPE_NOT; - rz_strbuf_appendf(&op->esil, "r%u,0xffffffff,^,r%u,=", + rz_strbuf_appendf(out, "r%u,0xffffffff,^,r%u,=", REG1(word1), REG2(word1)); - update_flags(op, V810_FLAG_S | V810_FLAG_Z); - clear_flags(op, V810_FLAG_OV); + update_flags(out, V810_FLAG_S | V810_FLAG_Z); + clear_flags(out, V810_FLAG_OV); break; case V810_DIV: case V810_DIVU: - op->type = RZ_ANALYSIS_OP_TYPE_DIV; - rz_strbuf_appendf(&op->esil, "r%u,r%u,/=,r%u,r%u,%%,r30,=", + rz_strbuf_appendf(out, "r%u,r%u,/=,r%u,r%u,%%,r30,=", REG1(word1), REG2(word1), REG1(word1), REG2(word1)); - update_flags(op, V810_FLAG_OV | V810_FLAG_S | V810_FLAG_Z); + update_flags(out, V810_FLAG_OV | V810_FLAG_S | V810_FLAG_Z); break; case V810_JMP: - if (REG1(word1) == 31) { - op->type = RZ_ANALYSIS_OP_TYPE_RET; - } else { - op->type = RZ_ANALYSIS_OP_TYPE_UJMP; - } - rz_strbuf_appendf(&op->esil, "r%u,pc,=", + rz_strbuf_appendf(out, "r%u,pc,=", REG1(word1)); break; case V810_OR: - op->type = RZ_ANALYSIS_OP_TYPE_OR; - rz_strbuf_appendf(&op->esil, "r%u,r%u,|=", + rz_strbuf_appendf(out, "r%u,r%u,|=", REG1(word1), REG2(word1)); - update_flags(op, V810_FLAG_S | V810_FLAG_Z); - clear_flags(op, V810_FLAG_OV); + update_flags(out, V810_FLAG_S | V810_FLAG_Z); + clear_flags(out, V810_FLAG_OV); break; case V810_ORI: - op->type = RZ_ANALYSIS_OP_TYPE_OR; - rz_strbuf_appendf(&op->esil, "%hu,r%u,|,r%u,=", + rz_strbuf_appendf(out, "%hu,r%u,|,r%u,=", word2, REG1(word1), REG2(word1)); - update_flags(op, V810_FLAG_S | V810_FLAG_Z); - clear_flags(op, V810_FLAG_OV); + update_flags(out, V810_FLAG_S | V810_FLAG_Z); + clear_flags(out, V810_FLAG_OV); break; case V810_MUL: case V810_MULU: - op->type = RZ_ANALYSIS_OP_TYPE_MUL; - rz_strbuf_appendf(&op->esil, "r%u,r%u,*=,32,r%u,r%u,*,>>,r30,=", + rz_strbuf_appendf(out, "r%u,r%u,*=,32,r%u,r%u,*,>>,r30,=", REG1(word1), REG2(word1), REG1(word1), REG2(word1)); - update_flags(op, V810_FLAG_OV | V810_FLAG_S | V810_FLAG_Z); + update_flags(out, V810_FLAG_OV | V810_FLAG_S | V810_FLAG_Z); break; case V810_XOR: - op->type = RZ_ANALYSIS_OP_TYPE_XOR; - rz_strbuf_appendf(&op->esil, "r%u,r%u,^=", + rz_strbuf_appendf(out, "r%u,r%u,^=", REG1(word1), REG2(word1)); - update_flags(op, V810_FLAG_S | V810_FLAG_Z); - clear_flags(op, V810_FLAG_OV); + update_flags(out, V810_FLAG_S | V810_FLAG_Z); + clear_flags(out, V810_FLAG_OV); break; case V810_XORI: - op->type = RZ_ANALYSIS_OP_TYPE_XOR; - rz_strbuf_appendf(&op->esil, "%hu,r%u,^,r%u,=", + rz_strbuf_appendf(out, "%hu,r%u,^,r%u,=", word2, REG1(word1), REG2(word1)); - update_flags(op, V810_FLAG_S | V810_FLAG_Z); - clear_flags(op, V810_FLAG_OV); + update_flags(out, V810_FLAG_S | V810_FLAG_Z); + clear_flags(out, V810_FLAG_OV); break; case V810_AND: - op->type = RZ_ANALYSIS_OP_TYPE_AND; - rz_strbuf_appendf(&op->esil, "r%u,r%u,&=", + rz_strbuf_appendf(out, "r%u,r%u,&=", REG1(word1), REG2(word1)); - update_flags(op, V810_FLAG_S | V810_FLAG_Z); - clear_flags(op, V810_FLAG_OV); + update_flags(out, V810_FLAG_S | V810_FLAG_Z); + clear_flags(out, V810_FLAG_OV); break; case V810_ANDI: - op->type = RZ_ANALYSIS_OP_TYPE_AND; - rz_strbuf_appendf(&op->esil, "%hu,r%u,&,r%u,=", + rz_strbuf_appendf(out, "%hu,r%u,&,r%u,=", word2, REG1(word1), REG2(word1)); - update_flags(op, V810_FLAG_Z); - clear_flags(op, V810_FLAG_OV | V810_FLAG_S); + update_flags(out, V810_FLAG_Z); + clear_flags(out, V810_FLAG_OV | V810_FLAG_S); break; case V810_CMP: - op->type = RZ_ANALYSIS_OP_TYPE_CMP; - rz_strbuf_appendf(&op->esil, "r%u,r%u,==", + rz_strbuf_appendf(out, "r%u,r%u,==", REG1(word1), REG2(word1)); - update_flags(op, -1); + update_flags(out, -1); break; case V810_CMP_IMM5: - op->type = RZ_ANALYSIS_OP_TYPE_CMP; - rz_strbuf_appendf(&op->esil, "%d,r%u,==", + rz_strbuf_appendf(out, "%d,r%u,==", (st8)SIGN_EXT_T5(IMM5(word1)), REG2(word1)); - update_flags(op, -1); + update_flags(out, -1); break; case V810_SUB: - op->type = RZ_ANALYSIS_OP_TYPE_SUB; - rz_strbuf_appendf(&op->esil, "r%u,r%u,-=", + rz_strbuf_appendf(out, "r%u,r%u,-=", REG1(word1), REG2(word1)); - update_flags(op, -1); + update_flags(out, -1); break; case V810_ADD: - op->type = RZ_ANALYSIS_OP_TYPE_ADD; - rz_strbuf_appendf(&op->esil, "r%u,r%u,+=", + rz_strbuf_appendf(out, "r%u,r%u,+=", REG1(word1), REG2(word1)); - update_flags(op, -1); + update_flags(out, -1); break; case V810_ADDI: - op->type = RZ_ANALYSIS_OP_TYPE_ADD; - rz_strbuf_appendf(&op->esil, "%hd,r%u,+,r%u,=", + rz_strbuf_appendf(out, "%hd,r%u,+,r%u,=", word2, REG1(word1), REG2(word1)); - update_flags(op, -1); + update_flags(out, -1); break; case V810_ADD_IMM5: - op->type = RZ_ANALYSIS_OP_TYPE_ADD; - rz_strbuf_appendf(&op->esil, "%d,r%u,+=", + rz_strbuf_appendf(out, "%d,r%u,+=", (st8)SIGN_EXT_T5(IMM5(word1)), REG2(word1)); - update_flags(op, -1); + update_flags(out, -1); break; case V810_SHR: - op->type = RZ_ANALYSIS_OP_TYPE_SHR; - rz_strbuf_appendf(&op->esil, "r%u,r%u,>>=", + rz_strbuf_appendf(out, "r%u,r%u,>>=", REG1(word1), REG2(word1)); - update_flags(op, V810_FLAG_CY | V810_FLAG_S | V810_FLAG_Z); - clear_flags(op, V810_FLAG_OV); + update_flags(out, V810_FLAG_CY | V810_FLAG_S | V810_FLAG_Z); + clear_flags(out, V810_FLAG_OV); break; case V810_SHR_IMM5: - op->type = RZ_ANALYSIS_OP_TYPE_SHR; - rz_strbuf_appendf(&op->esil, "%u,r%u,>>=", + rz_strbuf_appendf(out, "%u,r%u,>>=", (ut8)IMM5(word1), REG2(word1)); - update_flags(op, V810_FLAG_CY | V810_FLAG_S | V810_FLAG_Z); - clear_flags(op, V810_FLAG_OV); + update_flags(out, V810_FLAG_CY | V810_FLAG_S | V810_FLAG_Z); + clear_flags(out, V810_FLAG_OV); break; case V810_SAR: - op->type = RZ_ANALYSIS_OP_TYPE_SAR; reg1 = REG1(word1); reg2 = REG2(word1); - rz_strbuf_appendf(&op->esil, "31,r%u,>>,?{,r%u,32,-,r%u,1,<<,--,<<,}{,0,},r%u,r%u,>>,|,r%u,=", + rz_strbuf_appendf(out, "31,r%u,>>,?{,r%u,32,-,r%u,1,<<,--,<<,}{,0,},r%u,r%u,>>,|,r%u,=", reg2, reg1, reg1, reg1, reg2, reg2); - update_flags(op, V810_FLAG_CY | V810_FLAG_S | V810_FLAG_Z); - clear_flags(op, V810_FLAG_OV); + update_flags(out, V810_FLAG_CY | V810_FLAG_S | V810_FLAG_Z); + clear_flags(out, V810_FLAG_OV); break; case V810_SAR_IMM5: - op->type = RZ_ANALYSIS_OP_TYPE_SAR; imm5 = IMM5(word1); reg2 = REG2(word1); - rz_strbuf_appendf(&op->esil, "31,r%u,>>,?{,%u,32,-,%u,1,<<,--,<<,}{,0,},%u,r%u,>>,|,r%u,=", + rz_strbuf_appendf(out, "31,r%u,>>,?{,%u,32,-,%u,1,<<,--,<<,}{,0,},%u,r%u,>>,|,r%u,=", reg2, (ut8)imm5, (ut8)imm5, (ut8)imm5, reg2, reg2); - update_flags(op, V810_FLAG_CY | V810_FLAG_S | V810_FLAG_Z); - clear_flags(op, V810_FLAG_OV); + update_flags(out, V810_FLAG_CY | V810_FLAG_S | V810_FLAG_Z); + clear_flags(out, V810_FLAG_OV); break; case V810_SHL: - op->type = RZ_ANALYSIS_OP_TYPE_SHL; - rz_strbuf_appendf(&op->esil, "r%u,r%u,<<=", + rz_strbuf_appendf(out, "r%u,r%u,<<=", REG1(word1), REG2(word1)); - update_flags(op, V810_FLAG_CY | V810_FLAG_S | V810_FLAG_Z); - clear_flags(op, V810_FLAG_OV); + update_flags(out, V810_FLAG_CY | V810_FLAG_S | V810_FLAG_Z); + clear_flags(out, V810_FLAG_OV); break; case V810_SHL_IMM5: - op->type = RZ_ANALYSIS_OP_TYPE_SHL; - rz_strbuf_appendf(&op->esil, "%u,r%u,<<=", + rz_strbuf_appendf(out, "%u,r%u,<<=", (ut8)IMM5(word1), REG2(word1)); - update_flags(op, V810_FLAG_CY | V810_FLAG_S | V810_FLAG_Z); - clear_flags(op, V810_FLAG_OV); + update_flags(out, V810_FLAG_CY | V810_FLAG_S | V810_FLAG_Z); + clear_flags(out, V810_FLAG_OV); break; case V810_LDB: - op->type = RZ_ANALYSIS_OP_TYPE_LOAD; - rz_strbuf_appendf(&op->esil, "r%u,%hd,+,[1],r%u,=", + rz_strbuf_appendf(out, "r%u,%hd,+,[1],r%u,=", REG1(word1), word2, REG2(word1)); - rz_strbuf_appendf(&op->esil, ",DUP,0x80,&,?{,0xffffff00,|,}"); + rz_strbuf_appendf(out, ",DUP,0x80,&,?{,0xffffff00,|,}"); break; case V810_LDH: - op->type = RZ_ANALYSIS_OP_TYPE_LOAD; - rz_strbuf_appendf(&op->esil, "r%u,%hd,+,0xfffffffe,&,[2],r%u,=", + rz_strbuf_appendf(out, "r%u,%hd,+,0xfffffffe,&,[2],r%u,=", REG1(word1), word2, REG2(word1)); - rz_strbuf_appendf(&op->esil, ",DUP,0x8000,&,?{,0xffffff00,|,}"); + rz_strbuf_appendf(out, ",DUP,0x8000,&,?{,0xffffff00,|,}"); break; case V810_LDW: - op->type = RZ_ANALYSIS_OP_TYPE_LOAD; - rz_strbuf_appendf(&op->esil, "r%u,%hd,+,0xfffffffc,&,[4],r%u,=", + rz_strbuf_appendf(out, "r%u,%hd,+,0xfffffffc,&,[4],r%u,=", REG1(word1), word2, REG2(word1)); - rz_strbuf_appendf(&op->esil, ",DUP,0x80000000,&,?{,0xffffff00,|,}"); + rz_strbuf_appendf(out, ",DUP,0x80000000,&,?{,0xffffff00,|,}"); break; case V810_STB: - op->type = RZ_ANALYSIS_OP_TYPE_STORE; - rz_strbuf_appendf(&op->esil, "r%u,r%u,%hd,+,=[1]", + rz_strbuf_appendf(out, "r%u,r%u,%hd,+,=[1]", REG2(word1), REG1(word1), word2); break; case V810_STH: - op->type = RZ_ANALYSIS_OP_TYPE_STORE; - rz_strbuf_appendf(&op->esil, "r%u,r%u,%hd,+,0xfffffffe,&,=[2]", + rz_strbuf_appendf(out, "r%u,r%u,%hd,+,0xfffffffe,&,=[2]", REG2(word1), REG1(word1), word2); break; case V810_STW: - op->type = RZ_ANALYSIS_OP_TYPE_STORE; - rz_strbuf_appendf(&op->esil, "r%u,r%u,%hd,+,=[4]", + rz_strbuf_appendf(out, "r%u,r%u,%hd,+,=[4]", REG2(word1), REG1(word1), word2); break; case V810_INB: @@ -295,16 +231,198 @@ static int v810_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 case V810_INW: case V810_OUTB: case V810_OUTH: + case V810_OUTW: + break; + case V810_TRAP: + rz_strbuf_appendf(out, "%u,TRAP", IMM5(word1)); + break; + case V810_RETI: + // rz_strbuf_appendf (out, "np,?{,fepc,fepsw,}{,eipc,eipsw,},psw,=,pc,="); + break; + case V810_JAL: + case V810_JR: { + st32 jumpdisp = DISP26(word1, word2); + if (opcode == V810_JAL) { + rz_strbuf_appendf(out, "$$,4,+,r31,=,"); + } + rz_strbuf_appendf(out, "$$,%d,+,pc,=", jumpdisp); + break; + } + default: { + if (OPCODE(word1) >> 3 == 4) { + cond = COND(word1); + if (cond == V810_COND_NOP) { + break; + } + + st32 jumpdisp = DISP9(word1); + switch (cond) { + case V810_COND_V: + rz_strbuf_appendf(out, "ov"); + break; + case V810_COND_L: + rz_strbuf_appendf(out, "cy"); + break; + case V810_COND_E: + rz_strbuf_appendf(out, "z"); + break; + case V810_COND_NH: + rz_strbuf_appendf(out, "cy,z,|"); + break; + case V810_COND_N: + rz_strbuf_appendf(out, "s"); + break; + case V810_COND_NONE: + rz_strbuf_appendf(out, "1"); + break; + case V810_COND_LT: + rz_strbuf_appendf(out, "s,ov,^"); + break; + case V810_COND_LE: + rz_strbuf_appendf(out, "s,ov,^,z,|"); + break; + case V810_COND_NV: + rz_strbuf_appendf(out, "ov,!"); + break; + case V810_COND_NL: + rz_strbuf_appendf(out, "cy,!"); + break; + case V810_COND_NE: + rz_strbuf_appendf(out, "z,!"); + break; + case V810_COND_H: + rz_strbuf_appendf(out, "cy,z,|,!"); + break; + case V810_COND_P: + rz_strbuf_appendf(out, "s,!"); + break; + case V810_COND_GE: + rz_strbuf_appendf(out, "s,ov,^,!"); + break; + case V810_COND_GT: + rz_strbuf_appendf(out, "s,ov,^,z,|,!"); + break; + default: break; + } + rz_strbuf_appendf(out, ",?{,$$,%d,+,pc,=,}", jumpdisp); + } + break; + } + } +} + +static int v810_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask) { + int ret = 0; + ut8 opcode = 0, cond = 0; + ut16 word1 = 0, word2 = 0; + st32 jumpdisp = 0; + struct v810_cmd cmd; + + memset(&cmd, 0, sizeof(cmd)); + + ret = op->size = v810_decode_command(buf, len, &cmd); + if (ret <= 0) { + return ret; + } + + word1 = rz_read_ble16(buf, analysis->big_endian); + + if (ret == 4) { + word2 = rz_read_ble16(buf + 2, analysis->big_endian); + } + + op->addr = addr; + opcode = OPCODE(word1); + if (opcode >> 3 == 0x4) { + opcode &= 0x20; + } + + switch (opcode) { + case V810_MOV: + case V810_MOV_IMM5: + case V810_MOVHI: + case V810_MOVEA: + case V810_LDSR: + case V810_STSR: + op->type = RZ_ANALYSIS_OP_TYPE_MOV; + break; + case V810_NOT: + op->type = RZ_ANALYSIS_OP_TYPE_NOT; + break; + case V810_DIV: + case V810_DIVU: + op->type = RZ_ANALYSIS_OP_TYPE_DIV; + break; + case V810_OR: + case V810_ORI: + op->type = RZ_ANALYSIS_OP_TYPE_OR; + break; + case V810_MUL: + case V810_MULU: + op->type = RZ_ANALYSIS_OP_TYPE_MUL; + break; + case V810_XOR: + case V810_XORI: + op->type = RZ_ANALYSIS_OP_TYPE_XOR; + break; + case V810_AND: + case V810_ANDI: + op->type = RZ_ANALYSIS_OP_TYPE_AND; + break; + case V810_CMP: + case V810_CMP_IMM5: + op->type = RZ_ANALYSIS_OP_TYPE_CMP; + break; + case V810_SUB: + op->type = RZ_ANALYSIS_OP_TYPE_SUB; + break; + case V810_ADD: + case V810_ADDI: + case V810_ADD_IMM5: + op->type = RZ_ANALYSIS_OP_TYPE_ADD; + break; + case V810_SHR: + case V810_SHR_IMM5: + op->type = RZ_ANALYSIS_OP_TYPE_SHR; + break; + case V810_SAR: + case V810_SAR_IMM5: + op->type = RZ_ANALYSIS_OP_TYPE_SAR; + break; + case V810_SHL: + case V810_SHL_IMM5: + op->type = RZ_ANALYSIS_OP_TYPE_SHL; + break; + case V810_LDB: + case V810_LDH: + case V810_LDW: + op->type = RZ_ANALYSIS_OP_TYPE_LOAD; + break; + case V810_STB: + case V810_STH: + case V810_STW: + op->type = RZ_ANALYSIS_OP_TYPE_STORE; + break; + case V810_INB: + case V810_INH: + case V810_INW: + case V810_OUTB: + case V810_OUTH: case V810_OUTW: op->type = RZ_ANALYSIS_OP_TYPE_IO; break; case V810_TRAP: op->type = RZ_ANALYSIS_OP_TYPE_TRAP; - rz_strbuf_appendf(&op->esil, "%u,TRAP", IMM5(word1)); break; case V810_RETI: op->type = RZ_ANALYSIS_OP_TYPE_RET; - // rz_strbuf_appendf (&op->esil, "np,?{,fepc,fepsw,}{,eipc,eipsw,},psw,=,pc,="); + break; + case V810_JMP: + if (REG1(word1) == 31) { + op->type = RZ_ANALYSIS_OP_TYPE_RET; + } else { + op->type = RZ_ANALYSIS_OP_TYPE_UJMP; + } break; case V810_JAL: case V810_JR: @@ -314,76 +432,44 @@ static int v810_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 if (opcode == V810_JAL) { op->type = RZ_ANALYSIS_OP_TYPE_CALL; - rz_strbuf_appendf(&op->esil, "$$,4,+,r31,=,"); } else { op->type = RZ_ANALYSIS_OP_TYPE_JMP; } - - rz_strbuf_appendf(&op->esil, "$$,%d,+,pc,=", jumpdisp); break; - case V810_BCOND: - cond = COND(word1); - if (cond == V810_COND_NOP) { - op->type = RZ_ANALYSIS_OP_TYPE_NOP; - break; - } - - jumpdisp = DISP9(word1); - op->jump = addr + jumpdisp; - op->fail = addr + 2; - op->type = RZ_ANALYSIS_OP_TYPE_CJMP; + default: + if (OPCODE(word1) >> 3 == 4) { + cond = COND(word1); + if (cond == V810_COND_NOP) { + op->type = RZ_ANALYSIS_OP_TYPE_NOP; + break; + } - switch (cond) { - case V810_COND_V: - rz_strbuf_appendf(&op->esil, "ov"); - break; - case V810_COND_L: - rz_strbuf_appendf(&op->esil, "cy"); - break; - case V810_COND_E: - rz_strbuf_appendf(&op->esil, "z"); - break; - case V810_COND_NH: - rz_strbuf_appendf(&op->esil, "cy,z,|"); - break; - case V810_COND_N: - rz_strbuf_appendf(&op->esil, "s"); - break; - case V810_COND_NONE: - rz_strbuf_appendf(&op->esil, "1"); - break; - case V810_COND_LT: - rz_strbuf_appendf(&op->esil, "s,ov,^"); - break; - case V810_COND_LE: - rz_strbuf_appendf(&op->esil, "s,ov,^,z,|"); - break; - case V810_COND_NV: - rz_strbuf_appendf(&op->esil, "ov,!"); - break; - case V810_COND_NL: - rz_strbuf_appendf(&op->esil, "cy,!"); - break; - case V810_COND_NE: - rz_strbuf_appendf(&op->esil, "z,!"); - break; - case V810_COND_H: - rz_strbuf_appendf(&op->esil, "cy,z,|,!"); - break; - case V810_COND_P: - rz_strbuf_appendf(&op->esil, "s,!"); - break; - case V810_COND_GE: - rz_strbuf_appendf(&op->esil, "s,ov,^,!"); - break; - case V810_COND_GT: - rz_strbuf_appendf(&op->esil, "s,ov,^,z,|,!"); - break; + jumpdisp = DISP9(word1); + op->jump = addr + jumpdisp; + op->fail = addr + 2; + op->type = RZ_ANALYSIS_OP_TYPE_CJMP; } - rz_strbuf_appendf(&op->esil, ",?{,$$,%d,+,pc,=,}", jumpdisp); break; } + if (mask & RZ_ANALYSIS_OP_MASK_DISASM) { + op->mnemonic = rz_str_newf("%s %s", cmd.instr, cmd.operands); + } + + if (mask & RZ_ANALYSIS_OP_MASK_ESIL) { + v810_esil(&op->esil, opcode, word1, word2); + } + + if (mask & RZ_ANALYSIS_OP_MASK_IL) { + V810AnalysisContext ctx = { 0 }; + ctx.a = analysis; + ctx.w1 = word1; + ctx.w2 = word2; + ctx.pc = addr; + + op->il_op = v810_il_op(&ctx); + } + return ret; } @@ -431,15 +517,47 @@ static char *get_reg_profile(RzAnalysis *analysis) { "gpr r31 .32 124 0\n" "gpr pc .32 128 0\n" - "gpr psw .32 132 0\n" - "gpr np .1 132.16 0\n" - "gpr ep .1 132.17 0\n" - "gpr ae .1 132.18 0\n" - "gpr id .1 132.19 0\n" - "flg cy .1 132.28 0\n" - "flg ov .1 132.29 0\n" - "flg s .1 132.30 0\n" - "flg z .1 132.31 0\n"; + "gpr EIPC .32 132 0\n" + "gpr EIPSW .32 136 0\n" + "gpr FEPC .32 140 0\n" + "gpr FEPSW .32 144 0\n" + "gpr ECR .32 148 0\n" + "gpr PSW .32 152 0\n" + "gpr PIR .32 156 0\n" + "gpr TKCW .32 160 0\n" + "gpr Reserved_8 .32 164 0\n" + "gpr Reserved_9 .32 168 0\n" + "gpr Reserved_10 .32 172 0\n" + "gpr Reserved_11 .32 176 0\n" + "gpr Reserved_12 .32 180 0\n" + "gpr Reserved_13 .32 184 0\n" + "gpr Reserved_14 .32 188 0\n" + "gpr Reserved_15 .32 192 0\n" + "gpr Reserved_16 .32 196 0\n" + "gpr Reserved_17 .32 200 0\n" + "gpr Reserved_18 .32 204 0\n" + "gpr Reserved_19 .32 208 0\n" + "gpr Reserved_20 .32 212 0\n" + "gpr Reserved_21 .32 216 0\n" + "gpr Reserved_22 .32 220 0\n" + "gpr Reserved_23 .32 224 0\n" + "gpr CHCW .32 228 0\n" + "gpr ADTRE .32 232 0\n" + "gpr Reserved_26 .32 236 0\n" + "gpr Reserved_27 .32 240 0\n" + "gpr Reserved_28 .32 244 0\n" + "gpr Reserved_29 .32 248 0\n" + "gpr Reserved_30 .32 252 0\n" + "gpr Reserved_31 .32 256 0\n" + + "gpr np .1 152.16 0\n" + "gpr ep .1 152.17 0\n" + "gpr ae .1 152.18 0\n" + "gpr id .1 152.19 0\n" + "flg cy .1 152.28 0\n" + "flg ov .1 152.29 0\n" + "flg s .1 152.30 0\n" + "flg z .1 152.31 0\n"; return strdup(p); } @@ -452,6 +570,7 @@ RzAnalysisPlugin rz_analysis_plugin_v810 = { .bits = 32, .op = v810_op, .esil = true, + .il_config = v810_il_config, .get_reg_profile = get_reg_profile, }; diff --git a/librz/bin/format/elf/elf_info.c b/librz/bin/format/elf/elf_info.c index 6696998c691..26bf3d6b498 100644 --- a/librz/bin/format/elf/elf_info.c +++ b/librz/bin/format/elf/elf_info.c @@ -276,6 +276,7 @@ static const struct arch_translation arch_translation_table[] = { { EM_VIDEOCORE4, "vc4" }, { EM_MSP430, "msp430" }, { EM_SH, "sh" }, + { EM_V810, "v810" }, { EM_V800, "v850" }, { EM_V850, "v850" }, { EM_IA_64, "ia64" }, diff --git a/librz/bin/format/elf/glibc_elf.h b/librz/bin/format/elf/glibc_elf.h index 7a949cb1ec0..63b8bb91f82 100644 --- a/librz/bin/format/elf/glibc_elf.h +++ b/librz/bin/format/elf/glibc_elf.h @@ -374,6 +374,7 @@ typedef struct chances of collision with official or non-GNU unofficial values. */ #define EM_ALPHA 0x9026 +#define EM_V810 0x9081 /* Legal values for e_version (version). */ diff --git a/test/db/analysis/v810 b/test/db/analysis/v810 index b59a7f89044..94df424fc42 100644 --- a/test/db/analysis/v810 +++ b/test/db/analysis/v810 @@ -38,6 +38,37 @@ r29 = 0x00000000 r30 = 0x00000000 r31 = 0x00000000 pc = 0x00000000 -psw = 0x00000000 +EIPC = 0x00000000 +EIPSW = 0x00000000 +FEPC = 0x00000000 +FEPSW = 0x00000000 +ECR = 0x00000000 +PSW = 0x00000000 +PIR = 0x00000000 +TKCW = 0x00000000 +Reserved_8 = 0x00000000 +Reserved_9 = 0x00000000 +Reserved_10 = 0x00000000 +Reserved_11 = 0x00000000 +Reserved_12 = 0x00000000 +Reserved_13 = 0x00000000 +Reserved_14 = 0x00000000 +Reserved_15 = 0x00000000 +Reserved_16 = 0x00000000 +Reserved_17 = 0x00000000 +Reserved_18 = 0x00000000 +Reserved_19 = 0x00000000 +Reserved_20 = 0x00000000 +Reserved_21 = 0x00000000 +Reserved_22 = 0x00000000 +Reserved_23 = 0x00000000 +CHCW = 0x00000000 +ADTRE = 0x00000000 +Reserved_26 = 0x00000000 +Reserved_27 = 0x00000000 +Reserved_28 = 0x00000000 +Reserved_29 = 0x00000000 +Reserved_30 = 0x00000000 +Reserved_31 = 0x00000000 EOF RUN diff --git a/test/db/asm/v810 b/test/db/asm/v810 index e34f979531f..8d47ea75eb0 100644 --- a/test/db/asm/v810 +++ b/test/db/asm/v810 @@ -1,57 +1,57 @@ -d "mov r1, r2" 4100 -d "add r1, r2" 4104 -d "sub r1, r2" 4108 -d "cmp r1, r2" 410c -d "shl r1, r2" 4110 -d "shr r1, r2" 4114 -d "jmp [r1]" 0118 -d "sar r1, r2" 411c -d "mul r1, r2" 4120 -d "div r1, r2" 4124 -d "mulu r1, r2" 4128 -d "divu r1, r2" 412c -d "or r1, r2" 4130 -d "and r1, r2" 4134 -d "not r1, r2" 413c -d "mov -1, r2" 5f40 -d "add 1, r2" 4144 -d "cmp 0, r2" 404c -d "shl 8, r2" 4850 -d "shr 24, r2" 5854 -d "sar 0, r2" 405c -d "cli " 0058 -d "sei " 0078 -d "trap 15" 0f60 -d "reti " 0064 -d "halt " 0068 -d "ldsr FEPSW, r2" 4370 -d "stsr TKCW, r2" 4774 -d "stsr s8, r2" 4874 -d "bv -8" f881 -d "ble 8" 088e -d "movea 0xffff, r1, r2" 41a0ffff -d "addi -1, r1, r2" 41a4ffff -d "jr -8" ffabf8ff -d "jal 8" 00ac0800 -d "ori 0xff, r1, r2" 41b0ff00 -d "andi 0x0, r1, r2" 41b40000 -d "xori 0x0, r1, r2" 41b80000 -d "movhi 0x501, r1, r2" 41bc0105 -d "ld.b 0[r1], r2" 41c00000 -d "ld.h 32[r1], r2" 41c42000 -d "ld.w -32[r1], r2" 41cce0ff -d "st.b r2, -32[r1]" 41d0e0ff -d "st.h r2, 32[r1]" 41d42000 -d "st.w r2, 0[r1]" 41dc0000 -d "in.b 123[r1], r2" 41e07b00 -d "in.h 123[r1], r2" 41e47b00 -d "caxi 123[r1], r2" 41e87b00 -d "in.w 123[r1], r2" 41ec7b00 -d "out.b r2, 123[r1]" 41f07b00 -d "out.h r2, 123[r1]" 41f47b00 -d "out.w r2, 123[r1]" 41fc7b00 -d "mulf.s r11, r10" 4bf90018 -d "cvt.sw r10, r11" 6af9000c -d "subf.s r15, r30" cffb0014 -d "rev r15, r10" 4ff90028 -d "xb r11" 60f90020 \ No newline at end of file +d "mov r1, r2" 4100 0x0 (set r2 (var r1)) +d "add r1, r2" 4104 0x0 (seq (set result (+ (var r2) (var r1))) (set PSW (| (| (| (<< (ite (|| (&& (sle (var result) (var r2)) (! (== (var result) (var r2)))) (&& (sle (var result) (var r1)) (! (== (var result) (var r1))))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x3) false) (<< (ite (let _x (var result) (|| (! (sle (var _x) (bv 32 0x7fffffff))) (&& (sle (var _x) (bv 32 0x80000000)) (! (== (var _x) (bv 32 0x80000000)))))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false)) (<< (ite (&& (sle (var result) (bv 32 0x0)) (! (== (var result) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var result)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false))) (set r2 (var result))) +d "sub r1, r2" 4108 0x0 (seq (set result (- (var r2) (var r1))) (set PSW (| (| (| (<< (ite (&& (sle (var r2) (var r1)) (! (== (var r2) (var r1)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x3) false) (<< (ite (let _x (var result) (|| (! (sle (var _x) (bv 32 0x7fffffff))) (&& (sle (var _x) (bv 32 0x80000000)) (! (== (var _x) (bv 32 0x80000000)))))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false)) (<< (ite (&& (sle (var result) (bv 32 0x0)) (! (== (var result) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var result)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false))) (set r2 (var result))) +d "cmp r1, r2" 410c 0x0 (seq (set result (- (var r2) (var r1))) (set PSW (| (| (| (<< (ite (&& (sle (var r2) (var r1)) (! (== (var r2) (var r1)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x3) false) (<< (ite (let _x (var result) (|| (! (sle (var _x) (bv 32 0x7fffffff))) (&& (sle (var _x) (bv 32 0x80000000)) (! (== (var _x) (bv 32 0x80000000)))))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false)) (<< (ite (&& (sle (var result) (bv 32 0x0)) (! (== (var result) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var result)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false)))) +d "shl r1, r2" 4110 0x0 (seq (set result (<< (var r2) (var r1) false)) (set PSW (| (| (<< (ite (&& (! (is_zero (bv 32 0x1))) (! (is_zero (>> (var r2) (- (bv 32 0x20) (var r1)) false)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x3) false) (<< (ite (&& (sle (var result) (bv 32 0x0)) (! (== (var result) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var result)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false))) (set r2 (var result))) +d "shr r1, r2" 4114 0x0 (seq (set result (>> (var r2) (var r1) false)) (set PSW (| (| (<< (ite (&& (! (is_zero (bv 32 0x1))) (! (is_zero (& (var r2) (- (<< (bv 32 0x1) (bv 32 0x1) false) (bv 32 0x1)))))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x3) false) (<< (ite (&& (sle (var result) (bv 32 0x0)) (! (== (var result) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var result)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false))) (set r2 (var result))) +d "jmp [r1]" 0118 0x0 (jmp (& (var r1) (bv 32 0xfffffffe))) +d "sar r1, r2" 411c 0x0 (seq (set result (>> (var r2) (var r1) (msb (var r2)))) (set PSW (| (| (<< (ite (&& (! (is_zero (bv 32 0x1))) (! (is_zero (& (var r2) (- (<< (bv 32 0x1) (bv 32 0x1) false) (bv 32 0x1)))))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x3) false) (<< (ite (&& (sle (var result) (bv 32 0x0)) (! (== (var result) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var result)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false))) (set r2 (var result))) +d "mul r1, r2" 4120 0x0 (seq (set result (* (cast 64 (msb (var r2)) (var r2)) (cast 64 (msb (var r1)) (var r1)))) (set r2 (cast 32 false (var result))) (set r30 (cast 32 false (>> (var result) (bv 32 0x20) false))) (set PSW (| (| (<< (ite (let _x (var r2) (|| (! (sle (var _x) (bv 32 0x7fffffff))) (&& (sle (var _x) (bv 32 0x80000000)) (! (== (var _x) (bv 32 0x80000000)))))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false) (<< (ite (&& (sle (var r2) (bv 32 0x0)) (! (== (var r2) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var r2)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false)))) +d "div r1, r2" 4124 0x0 (seq (set r2 (div (var r2) (var r1))) (set r30 (mod (var r2) (var r1))) (set PSW (| (| (<< (ite (let _x (var r2) (|| (! (sle (var _x) (bv 32 0x7fffffff))) (&& (sle (var _x) (bv 32 0x80000000)) (! (== (var _x) (bv 32 0x80000000)))))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false) (<< (ite (&& (sle (var r2) (bv 32 0x0)) (! (== (var r2) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var r2)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false)))) +d "mulu r1, r2" 4128 0x0 (seq (set result (* (cast 64 false (var r2)) (cast 64 false (var r1)))) (set r2 (cast 32 false (var result))) (set r30 (cast 32 false (>> (var result) (bv 32 0x20) false))) (set PSW (| (| (<< (ite (let _x (var r2) (|| (! (sle (var _x) (bv 32 0x7fffffff))) (&& (sle (var _x) (bv 32 0x80000000)) (! (== (var _x) (bv 32 0x80000000)))))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false) (<< (ite (&& (sle (var r2) (bv 32 0x0)) (! (== (var r2) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var r2)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false)))) +d "divu r1, r2" 412c 0x0 (seq (set r2 (div (var r2) (var r1))) (set r30 (mod (var r2) (var r1))) (set PSW (| (| (<< (ite false (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false) (<< (ite (&& (sle (var r2) (bv 32 0x0)) (! (== (var r2) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var r2)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false)))) +d "or r1, r2" 4130 0x0 (seq (set result (| (var r2) (var r1))) (set PSW (| (| (<< (ite false (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false) (<< (ite (&& (sle (var r2) (bv 32 0x0)) (! (== (var r2) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var r2)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false))) (set r2 (var result))) +d "and r1, r2" 4134 0x0 (seq (set result (& (var r2) (var r1))) (set PSW (| (| (<< (ite false (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false) (<< (ite (&& (sle (var r2) (bv 32 0x0)) (! (== (var r2) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var r2)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false))) (set r2 (var result))) +d "not r1, r2" 413c 0x0 (seq (set r2 (~ (var r1))) (set PSW (| (| (<< (ite false (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false) (<< (ite (&& (sle (var r2) (bv 32 0x0)) (! (== (var r2) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var r2)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false)))) +d "mov -1, r2" 5f40 0x0 (set r2 (bv 32 0xffffffff)) +d "add 1, r2" 4144 0x0 (seq (set result (+ (var r2) (bv 32 0x1))) (set PSW (| (| (| (<< (ite (|| (&& (sle (var result) (var r2)) (! (== (var result) (var r2)))) (&& (sle (var result) (bv 32 0x1)) (! (== (var result) (bv 32 0x1))))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x3) false) (<< (ite (let _x (var result) (|| (! (sle (var _x) (bv 32 0x7fffffff))) (&& (sle (var _x) (bv 32 0x80000000)) (! (== (var _x) (bv 32 0x80000000)))))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false)) (<< (ite (&& (sle (var result) (bv 32 0x0)) (! (== (var result) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var result)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false))) (set r2 (var result))) +d "cmp 0, r2" 404c 0x0 (seq (set result (- (var r2) (bv 32 0x0))) (set PSW (| (| (| (<< (ite (&& (sle (var r2) (bv 32 0x0)) (! (== (var r2) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x3) false) (<< (ite (let _x (var result) (|| (! (sle (var _x) (bv 32 0x7fffffff))) (&& (sle (var _x) (bv 32 0x80000000)) (! (== (var _x) (bv 32 0x80000000)))))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false)) (<< (ite (&& (sle (var result) (bv 32 0x0)) (! (== (var result) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var result)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false)))) +d "shl 8, r2" 4850 0x0 (seq (set result (<< (var r2) (bv 32 0x8) false)) (set PSW (| (| (<< (ite (&& (! (is_zero (bv 32 0x8))) (! (is_zero (>> (var r2) (- (bv 32 0x20) (bv 32 0x8)) false)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x3) false) (<< (ite (&& (sle (var result) (bv 32 0x0)) (! (== (var result) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var result)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false))) (set r2 (var result))) +d "shr 24, r2" 5854 0x0 (seq (set result (>> (var r2) (bv 32 0x18) false)) (set PSW (| (| (<< (ite (&& (! (is_zero (var r24))) (! (is_zero (& (var r2) (- (<< (bv 32 0x1) (var r24) false) (bv 32 0x1)))))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x3) false) (<< (ite (&& (sle (var result) (bv 32 0x0)) (! (== (var result) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var result)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false))) (set r2 (var result))) +d "sar 0, r2" 405c 0x0 (seq (set result (>> (var r2) (bv 32 0x0) (msb (var r2)))) (set PSW (| (| (<< (ite (&& (! (is_zero (var r0))) (! (is_zero (& (var r2) (- (<< (bv 32 0x1) (var r0) false) (bv 32 0x1)))))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x3) false) (<< (ite (&& (sle (var result) (bv 32 0x0)) (! (== (var result) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var result)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false))) (set r2 (var result))) +d "cli" 0058 0x0 nop +d "sei" 0078 0x0 nop +d "trap 15" 0f60 0x0 nop +d "reti" 0064 0x0 (seq (set _pc (ite (let _v_part (let _v_parent (var PSW) (& (>> (var _v_parent) (bv 32 0xf) false) (bv 32 0x1))) (! (is_zero (var _v_part)))) (var FEPC) (var EIPC))) (set PSW (ite (let _v_part (let _v_parent (var PSW) (& (>> (var _v_parent) (bv 32 0xf) false) (bv 32 0x1))) (! (is_zero (var _v_part)))) (var FEPSW) (var EIPSW))) (jmp (var _pc))) +d "halt" 0068 0x0 nop +d "ldsr FEPSW, r2" 4370 0x0 (set FEPSW (var r2)) +d "stsr TKCW, r2" 4774 0x0 (set r2 (var TKCW)) +d "stsr s8, r2" 4874 0x0 (set r2 (var Reserved_8)) +d "bv -8" f881 0x0 (branch (let _v_part (let _v_parent (var PSW) (& (>> (var _v_parent) (bv 32 0x2) false) (bv 32 0x1))) (! (is_zero (var _v_part)))) (seq (set _pc (+ (bv 32 0x0) (bv 32 0xfffffff8))) (jmp (var _pc))) nop) +d "ble 8" 088e 0x0 (branch (|| (^^ (let _v_part (let _v_parent (var PSW) (& (>> (var _v_parent) (bv 32 0x1) false) (bv 32 0x1))) (! (is_zero (var _v_part)))) (let _v_part (let _v_parent (var PSW) (& (>> (var _v_parent) (bv 32 0x2) false) (bv 32 0x1))) (! (is_zero (var _v_part))))) (let _v_part (let _v_parent (var PSW) (& (>> (var _v_parent) (bv 32 0x0) false) (bv 32 0x1))) (! (is_zero (var _v_part))))) (seq (set _pc (+ (bv 32 0x0) (bv 32 0x8))) (jmp (var _pc))) nop) +d "movea 0xffff, r1, r2" 41a0ffff 0x0 (set r2 (+ (var r1) (bv 32 0xffffffff))) +d "addi -1, r1, r2" 41a4ffff 0x0 (seq (set result (+ (var r1) (bv 32 0xffffffff))) (set PSW (| (| (| (<< (ite (|| (&& (sle (var result) (bv 32 0xffffffff)) (! (== (var result) (bv 32 0xffffffff)))) (&& (sle (var result) (var r1)) (! (== (var result) (var r1))))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x3) false) (<< (ite (let _x (var result) (|| (! (sle (var _x) (bv 32 0x7fffffff))) (&& (sle (var _x) (bv 32 0x80000000)) (! (== (var _x) (bv 32 0x80000000)))))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false)) (<< (ite (&& (sle (var result) (bv 32 0x0)) (! (== (var result) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var result)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false))) (set r2 (var result))) +d "jr -8" ffabf8ff 0x0 (seq (set _pc (+ (bv 32 0x0) (bv 32 0xfffffff8))) (jmp (var _pc))) +d "jal 8" 00ac0800 0x0 (seq (set r31 (+ (bv 32 0x0) (bv 32 0x4))) (set _pc (+ (bv 32 0x0) (bv 32 0x8))) (jmp (var _pc))) +d "ori 0xff, r1, r2" 41b0ff00 0x0 (seq (set result (| (var r2) (bv 32 0xff))) (set PSW (| (| (<< (ite false (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false) (<< (ite (&& (sle (var r2) (bv 32 0x0)) (! (== (var r2) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var r2)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false))) (set r2 (var result))) +d "andi 0x0, r1, r2" 41b40000 0x0 (seq (set result (& (var r2) (bv 32 0x0))) (set PSW (| (| (<< (ite false (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false) (<< (ite false (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var r2)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false))) (set r2 (var result))) +d "xori 0x0, r1, r2" 41b80000 0x0 (seq (set result (^ (var r2) (bv 32 0x0))) (set PSW (| (| (<< (ite false (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false) (<< (ite (&& (sle (var r2) (bv 32 0x0)) (! (== (var r2) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var r2)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false))) (set r2 (var result))) +d "movhi 0x501, r1, r2" 41bc0105 0x0 (set r2 (+ (var r1) (<< (bv 32 0x501) (bv 32 0x10) false))) +d "ld.b 0[r1], r2" 41c00000 0x0 (seq (set _adr (+ (var r1) (bv 32 0x0))) (set r2 (let _v (cast 32 false (loadw 0 8 (var _adr))) (>> (cast 32 false (<< (var _v) (- (- (bv 32 0x20) (bv 32 0x8)) (bv 32 0x0)) false)) (- (bv 32 0x20) (bv 32 0x8)) (msb (cast 32 false (<< (var _v) (- (- (bv 32 0x20) (bv 32 0x8)) (bv 32 0x0)) false))))))) +d "ld.h 32[r1], r2" 41c42000 0x0 (seq (set _adr (+ (var r1) (bv 32 0x20))) (set r2 (let _v (cast 32 false (loadw 0 16 (var _adr))) (>> (cast 32 false (<< (var _v) (- (- (bv 32 0x20) (bv 32 0x10)) (bv 32 0x0)) false)) (- (bv 32 0x20) (bv 32 0x10)) (msb (cast 32 false (<< (var _v) (- (- (bv 32 0x20) (bv 32 0x10)) (bv 32 0x0)) false))))))) +d "ld.w -32[r1], r2" 41cce0ff 0x0 (seq (set _adr (+ (var r1) (bv 32 0xffffffe0))) (set r2 (loadw 0 32 (var _adr)))) +d "st.b r2, -32[r1]" 41d0e0ff 0x0 (seq (set _adr (+ (var r1) (bv 32 0xffffffe0))) (storew 0 (var _adr) (cast 8 false (var r2)))) +d "st.h r2, 32[r1]" 41d42000 0x0 (seq (set _adr (+ (var r1) (bv 32 0x20))) (storew 0 (var _adr) (cast 16 false (var r2)))) +d "st.w r2, 0[r1]" 41dc0000 0x0 (seq (set _adr (+ (var r1) (bv 32 0x0))) (storew 0 (var _adr) (var r2))) +d "in.b 123[r1], r2" 41e07b00 0x0 (seq (set _adr (+ (var r1) (bv 32 0x7b))) (set r2 (let _v (cast 32 false (loadw 0 8 (var _adr))) (>> (cast 32 false (<< (var _v) (- (- (bv 32 0x20) (bv 32 0x8)) (bv 32 0x0)) false)) (- (bv 32 0x20) (bv 32 0x8)) (msb (cast 32 false (<< (var _v) (- (- (bv 32 0x20) (bv 32 0x8)) (bv 32 0x0)) false))))))) +d "in.h 123[r1], r2" 41e47b00 0x0 (seq (set _adr (+ (var r1) (bv 32 0x7b))) (set r2 (let _v (cast 32 false (loadw 0 16 (var _adr))) (>> (cast 32 false (<< (var _v) (- (- (bv 32 0x20) (bv 32 0x10)) (bv 32 0x0)) false)) (- (bv 32 0x20) (bv 32 0x10)) (msb (cast 32 false (<< (var _v) (- (- (bv 32 0x20) (bv 32 0x10)) (bv 32 0x0)) false))))))) +d "caxi 123[r1], r2" 41e87b00 0x0 (seq (set _adr (+ (var r1) (bv 32 0x7b))) (set _tmp (loadw 0 32 (var _adr))) (set result (- (var r2) (var _tmp))) (set PSW (| (| (| (<< (ite (&& (sle (var r2) (var r1)) (! (== (var r2) (var r1)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x3) false) (<< (ite (let _x (var result) (|| (! (sle (var _x) (bv 32 0x7fffffff))) (&& (sle (var _x) (bv 32 0x80000000)) (! (== (var _x) (bv 32 0x80000000)))))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false)) (<< (ite (&& (sle (var result) (bv 32 0x0)) (! (== (var result) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var result)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false))) (branch (is_zero (var result)) (seq (storew 0 (var _adr) (var r30)) (set r2 (var _tmp))) (seq (storew 0 (var _adr) (var _tmp)) (set r2 (var _tmp))))) +d "in.w 123[r1], r2" 41ec7b00 0x0 (seq (set _adr (+ (var r1) (bv 32 0x7b))) (set r2 (loadw 0 32 (var _adr)))) +d "out.b r2, 123[r1]" 41f07b00 0x0 (seq (set _adr (+ (var r1) (bv 32 0x7b))) (storew 0 (var _adr) (cast 8 false (var r2)))) +d "out.h r2, 123[r1]" 41f47b00 0x0 (seq (set _adr (+ (var r1) (bv 32 0x7b))) (storew 0 (var _adr) (cast 16 false (var r2)))) +d "out.w r2, 123[r1]" 41fc7b00 0x0 (seq (set _adr (+ (var r1) (bv 32 0x7b))) (storew 0 (var _adr) (var r2))) +d "mulf.s r11, r10" 4bf90018 0x0 (seq (set result (*. rne (float 0 (var r10) ) (float 0 (var r11) ))) (set PSW (| (| (| (| (| (<< (ite (! (is_fpos (var result))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x3) false) (<< (ite false (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false)) (<< (ite (&& (! (|| (is_nan (var result)) (is_nan (float 0 (bv 32 0x0) )))) (<. (var result) (float 0 (bv 32 0x0) ))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_fzero (var result)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false)) (<< (ite (|| (is_nan (var result)) (is_inf (var result))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x9) false)) (<< (ite (is_fzero (float 0 (var r11) )) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x7) false))) (set r10 (fbits (var result)))) +d "cvt.sw r10, r11" 6af9000c 0x0 (seq (set r11 (fcast_sint 32 rne (float 0 (var r10) ))) (set PSW (| (| (<< (ite false (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false) (<< (ite (&& (sle (var r11) (bv 32 0x0)) (! (== (var r11) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_zero (var r11)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false)))) +d "subf.s r15, r30" cffb0014 0x0 (seq (set result (-. rne (float 0 (var r30) ) (float 0 (var r15) ))) (set PSW (| (| (| (| (| (<< (ite (! (is_fpos (var result))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x3) false) (<< (ite false (bv 32 0x1) (bv 32 0x0)) (bv 32 0x2) false)) (<< (ite (&& (! (|| (is_nan (var result)) (is_nan (float 0 (bv 32 0x0) )))) (<. (var result) (float 0 (bv 32 0x0) ))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1) false)) (<< (ite (is_fzero (var result)) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x0) false)) (<< (ite (|| (is_nan (var result)) (is_inf (var result))) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x9) false)) (<< (ite (is_fzero (float 0 (var r15) )) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x7) false))) (set r30 (fbits (var result)))) +d "rev r15, r10" 4ff90028 0x0 nop +d "xb r11" 60f90020 0x0 nop diff --git a/test/db/rzil/v810 b/test/db/rzil/v810 new file mode 100644 index 00000000000..a5738e5a43b --- /dev/null +++ b/test/db/rzil/v810 @@ -0,0 +1,15 @@ +NAME=Testing the decryption in emulateme +FILE=bins/v810/emulateme.v810 +TIMEOUT=30 +CMDS=<