From 8f7f03cff69a3edfd42b06d8234c86608b1c8fe1 Mon Sep 17 00:00:00 2001 From: billow Date: Mon, 1 Apr 2024 07:45:33 +0800 Subject: [PATCH] TriCore IL: fix `CSUB/CSUBN` (#4409) --- librz/arch/isa/tricore/tricore_il.c | 30 ++++++++++++++++++----------- test/db/asm/tricore | 4 ++-- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/librz/arch/isa/tricore/tricore_il.c b/librz/arch/isa/tricore/tricore_il.c index 553491b5f31..89385239353 100644 --- a/librz/arch/isa/tricore/tricore_il.c +++ b/librz/arch/isa/tricore/tricore_il.c @@ -484,6 +484,8 @@ static RzILOpPure *VARG_wrap(const char *name) { #undef VARG #define VARG(n) VARG_wrap(n) +static RzAnalysisLiftedILOp status_conditional(RzILOpPure *cnd); + static RzAnalysisLiftedILOp ST_MB(RzILOpPure *dst, size_t n, ...) { rz_return_val_if_fail(dst && n > 0, rz_il_op_new_nop()); va_list args; @@ -2006,9 +2008,11 @@ static RzILOpEffect *e_op2_cond( const char *r, RzILOpPure *a, RzILOpPure *b, RzILOpPure *cond, RzILOpPure *(*op)(RzILOpPure *x, RzILOpPure *y)) { - RzILOpEffect *e = SEQ2(SETL("result", op(a, b)), - SETG(r, VARL("result"))); - return f_overflow32(e); + return SEQ4( + SETL("condition", cond), + SETL("result", ITE(VARL("condition"), op(a, b), DUP(a))), + SETG(r, VARL("result")), + status_conditional(VARL("condition"))); } static RzILOpEffect *packed_op2_sov( @@ -2192,18 +2196,22 @@ static RzAnalysisLiftedILOp lift_add(RzAsmTriCoreContext *ctx) { return NULL; } +static RzAnalysisLiftedILOp status_conditional(RzILOpPure *cnd) { + return SEQ6( + SETL("overflow", OR(SGT(VARL("result"), S32(0x7FFFFFFF)), SLT(VARL("result"), S32(-80000000)))), + BRANCH(cnd, set_PSW_V(BOOL_TO_BV32(VARL("overflow"))), NOP()), + BRANCH(AND(DUP(cnd), VARL("overflow")), set_PSW_SV(U32(1)), NOP()), + SETL("advanced_overflow", XOR(NON_ZERO(BITS32(VARL("result"), 30, 1)), NON_ZERO(BITS32(VARL("result"), 31, 1)))), + BRANCH(DUP(cnd), set_PSW_AV(BOOL_TO_BV32(VARL("advanced_overflow"))), NOP()), + BRANCH(AND(DUP(cnd), VARL("advanced_overflow")), set_PSW_SAV(U32(1)), NOP())); +} + static RzAnalysisLiftedILOp e_cadd(const char *dst, RzILOpPure *cnd, RzILOpPure *a, RzILOpPure *b) { - return SEQ9( + return SEQ4( SETL("condition", cnd), SETL("result", ITE(VARL("condition"), ADD(a, b), DUP(a))), SETG(dst, VARL("result")), - /// Status - SETL("overflow", OR(SGT(VARL("result"), S32(0x7FFFFFFF)), SLT(VARL("result"), S32(-80000000)))), - BRANCH(VARL("condition"), set_PSW_V(BOOL_TO_BV32(VARL("overflow"))), NOP()), - BRANCH(AND(VARL("condition"), VARL("overflow")), set_PSW_SV(U32(1)), NOP()), - SETL("advanced_overflow", XOR(NON_ZERO(BITS32(VARL("result"), 30, 1)), NON_ZERO(BITS32(VARL("result"), 31, 1)))), - BRANCH(VARL("condition"), set_PSW_AV(BOOL_TO_BV32(VARL("advanced_overflow"))), NOP()), - BRANCH(AND(VARL("condition"), VARL("advanced_overflow")), set_PSW_SAV(U32(1)), NOP())); + status_conditional(VARL("condition"))); } static RzAnalysisLiftedILOp lift_cadd(RzAsmTriCoreContext *ctx) { diff --git a/test/db/asm/tricore b/test/db/asm/tricore index db0758a29de..f87f0847467 100644 --- a/test/db/asm/tricore +++ b/test/db/asm/tricore @@ -657,8 +657,8 @@ d "subs.u d0, d0, d0" 0b00b000 0x0 (seq (set result (let x (- (var d0) (var d0)) d "subx d0, d0, d0" 0b00c000 0x0 (seq (set result (- (var d0) (var d0))) (set d0 (var result)) (set carry_out (& (>> (+ (+ (var d0) (~- (var d0))) (bv 32 0x1)) (bv 32 0x0) false) (bv 32 0x1))) (set PSW (| (& (var PSW) (bv 32 0x7fffffff)) (<< (& (var carry_out) (bv 32 0x1)) (bv 32 0x1f) false)))) d "sub.b d0, d0, d0" 0b008004 0x0 (seq (set result_byte3 (- (cast 8 false (& (>> (var d0) (bv 32 0x18) false) (bv 32 0xff))) (cast 8 false (& (>> (var d0) (bv 32 0x18) false) (bv 32 0xff))))) (set result_byte2 (- (cast 8 false (& (>> (var d0) (bv 32 0x10) false) (bv 32 0xff))) (cast 8 false (& (>> (var d0) (bv 32 0x10) false) (bv 32 0xff))))) (set result_byte1 (- (cast 8 false (& (>> (var d0) (bv 32 0x8) false) (bv 32 0xff))) (cast 8 false (& (>> (var d0) (bv 32 0x8) false) (bv 32 0xff))))) (set result_byte0 (- (cast 8 false (& (>> (var d0) (bv 32 0x0) false) (bv 32 0xff))) (cast 8 false (& (>> (var d0) (bv 32 0x0) false) (bv 32 0xff))))) (set result (| (cast 32 false (<< (var result_byte3) (bv 32 0x18) false)) (| (cast 32 false (<< (var result_byte2) (bv 32 0x10) false)) (| (cast 32 false (<< (var result_byte1) (bv 32 0x8) false)) (cast 32 false (var result_byte0)))))) (set d0 (var result)) (set ov3 (|| (! (ule (var result_byte3) (bv 8 0x7f))) (&& (sle (var result_byte3) (bv 8 0x80)) (! (== (var result_byte3) (bv 8 0x80)))))) (set ov2 (|| (! (ule (var result_byte2) (bv 8 0x7f))) (&& (sle (var result_byte2) (bv 8 0x80)) (! (== (var result_byte2) (bv 8 0x80)))))) (set ov1 (|| (! (ule (var result_byte1) (bv 8 0x7f))) (&& (sle (var result_byte1) (bv 8 0x80)) (! (== (var result_byte1) (bv 8 0x80)))))) (set ov0 (|| (! (ule (var result_byte0) (bv 8 0x7f))) (&& (sle (var result_byte0) (bv 8 0x80)) (! (== (var result_byte0) (bv 8 0x80)))))) (set overflow (|| (|| (var ov1) (var ov0)) (|| (var ov3) (var ov2)))) (set aov3 (^^ (! (is_zero (& (>> (var result_byte3) (bv 8 0x7) false) (bv 8 0x1)))) (! (is_zero (& (>> (var result_byte3) (bv 8 0x6) false) (bv 8 0x1)))))) (set aov2 (^^ (! (is_zero (& (>> (var result_byte2) (bv 8 0x7) false) (bv 8 0x1)))) (! (is_zero (& (>> (var result_byte2) (bv 8 0x6) false) (bv 8 0x1)))))) (set aov1 (^^ (! (is_zero (& (>> (var result_byte1) (bv 8 0x7) false) (bv 8 0x1)))) (! (is_zero (& (>> (var result_byte1) (bv 8 0x6) false) (bv 8 0x1)))))) (set aov0 (^^ (! (is_zero (& (>> (var result_byte0) (bv 8 0x7) false) (bv 8 0x1)))) (! (is_zero (& (>> (var result_byte0) (bv 8 0x6) false) (bv 8 0x1)))))) (set advanced_overflow (|| (|| (var aov1) (var aov0)) (|| (var aov3) (var aov2)))) (set PSW (| (& (var PSW) (bv 32 0xbfffffff)) (<< (& (ite (var overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1e) false))) (set PSW (| (& (var PSW) (bv 32 0xefffffff)) (<< (& (ite (var advanced_overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1c) false))) (branch (var overflow) (set PSW (| (& (var PSW) (bv 32 0xdfffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1d) false))) nop) (branch (var advanced_overflow) (set PSW (| (& (var PSW) (bv 32 0xf7ffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1b) false))) nop)) d "sub.h d0, d0, d0" 0b008006 0x0 (seq (set result_hw1 (- (cast 16 false (& (>> (var d0) (bv 32 0x10) false) (bv 32 0xffff))) (cast 16 false (& (>> (var d0) (bv 32 0x10) false) (bv 32 0xffff))))) (set result_hw0 (- (cast 16 false (& (>> (var d0) (bv 32 0x0) false) (bv 32 0xffff))) (cast 16 false (& (>> (var d0) (bv 32 0x0) false) (bv 32 0xffff))))) (set result (| (cast 32 false (<< (var result_hw1) (bv 32 0x10) false)) (cast 32 false (var result_hw0)))) (set d0 (var result)) (set ov1 (|| (! (ule (var result_hw1) (bv 16 0x7fff))) (&& (sle (var result_hw1) (bv 16 0x8000)) (! (== (var result_hw1) (bv 16 0x8000)))))) (set ov0 (|| (! (ule (var result_hw0) (bv 16 0x7fff))) (&& (sle (var result_hw0) (bv 16 0x8000)) (! (== (var result_hw0) (bv 16 0x8000)))))) (set overflow (|| (var ov1) (var ov0))) (set aov1 (^^ (! (is_zero (& (>> (var result_hw1) (bv 16 0xf) false) (bv 16 0x1)))) (! (is_zero (& (>> (var result_hw1) (bv 16 0xe) false) (bv 16 0x1)))))) (set aov0 (^^ (! (is_zero (& (>> (var result_hw0) (bv 16 0xf) false) (bv 16 0x1)))) (! (is_zero (& (>> (var result_hw0) (bv 16 0xe) false) (bv 16 0x1)))))) (set advanced_overflow (|| (var aov1) (var aov0))) (set PSW (| (& (var PSW) (bv 32 0xbfffffff)) (<< (& (ite (var overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1e) false))) (set PSW (| (& (var PSW) (bv 32 0xefffffff)) (<< (& (ite (var advanced_overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1c) false))) (branch (var overflow) (set PSW (| (& (var PSW) (bv 32 0xdfffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1d) false))) nop) (branch (var advanced_overflow) (set PSW (| (& (var PSW) (bv 32 0xf7ffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1b) false))) nop)) -d "csub d0, d0, d0, d0" 2b002000 0x0 (seq (set result (- (var d0) (var d0))) (set d0 (var result)) (set overflow (|| (! (ule (var result) (bv 32 0x7fffffff))) (&& (sle (var result) (bv 32 0x80000000)) (! (== (var result) (bv 32 0x80000000)))))) (set advanced_overflow (^^ (! (is_zero (& (>> (var result) (bv 32 0x1f) false) (bv 32 0x1)))) (! (is_zero (& (>> (var result) (bv 32 0x1e) false) (bv 32 0x1)))))) (set PSW (| (& (var PSW) (bv 32 0xbfffffff)) (<< (& (ite (var overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1e) false))) (set PSW (| (& (var PSW) (bv 32 0xefffffff)) (<< (& (ite (var advanced_overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1c) false))) (branch (var overflow) (set PSW (| (& (var PSW) (bv 32 0xdfffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1d) false))) nop) (branch (var advanced_overflow) (set PSW (| (& (var PSW) (bv 32 0xf7ffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1b) false))) nop)) -d "csubn d0, d0, d0, d0" 2b003000 0x0 (seq (set result (- (var d0) (var d0))) (set d0 (var result)) (set overflow (|| (! (ule (var result) (bv 32 0x7fffffff))) (&& (sle (var result) (bv 32 0x80000000)) (! (== (var result) (bv 32 0x80000000)))))) (set advanced_overflow (^^ (! (is_zero (& (>> (var result) (bv 32 0x1f) false) (bv 32 0x1)))) (! (is_zero (& (>> (var result) (bv 32 0x1e) false) (bv 32 0x1)))))) (set PSW (| (& (var PSW) (bv 32 0xbfffffff)) (<< (& (ite (var overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1e) false))) (set PSW (| (& (var PSW) (bv 32 0xefffffff)) (<< (& (ite (var advanced_overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1c) false))) (branch (var overflow) (set PSW (| (& (var PSW) (bv 32 0xdfffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1d) false))) nop) (branch (var advanced_overflow) (set PSW (| (& (var PSW) (bv 32 0xf7ffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1b) false))) nop)) +d "csub d0, d0, d0, d0" 2b002000 0x0 (seq (set condition (! (is_zero (var d0)))) (set result (ite (var condition) (- (var d0) (var d0)) (var d0))) (set d0 (var result)) (set overflow (|| (! (sle (var result) (bv 32 0x7fffffff))) (&& (sle (var result) (bv 32 0xfb3b4c00)) (! (== (var result) (bv 32 0xfb3b4c00)))))) (branch (var condition) (set PSW (| (& (var PSW) (bv 32 0xbfffffff)) (<< (& (ite (var overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1e) false))) nop) (branch (&& (var condition) (var overflow)) (set PSW (| (& (var PSW) (bv 32 0xdfffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1d) false))) nop) (set advanced_overflow (^^ (! (is_zero (& (>> (var result) (bv 32 0x1e) false) (bv 32 0x1)))) (! (is_zero (& (>> (var result) (bv 32 0x1f) false) (bv 32 0x1)))))) (branch (var condition) (set PSW (| (& (var PSW) (bv 32 0xefffffff)) (<< (& (ite (var advanced_overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1c) false))) nop) (branch (&& (var condition) (var advanced_overflow)) (set PSW (| (& (var PSW) (bv 32 0xf7ffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1b) false))) nop)) +d "csubn d0, d0, d0, d0" 2b003000 0x0 (seq (set condition (is_zero (var d0))) (set result (ite (var condition) (- (var d0) (var d0)) (var d0))) (set d0 (var result)) (set overflow (|| (! (sle (var result) (bv 32 0x7fffffff))) (&& (sle (var result) (bv 32 0xfb3b4c00)) (! (== (var result) (bv 32 0xfb3b4c00)))))) (branch (var condition) (set PSW (| (& (var PSW) (bv 32 0xbfffffff)) (<< (& (ite (var overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1e) false))) nop) (branch (&& (var condition) (var overflow)) (set PSW (| (& (var PSW) (bv 32 0xdfffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1d) false))) nop) (set advanced_overflow (^^ (! (is_zero (& (>> (var result) (bv 32 0x1e) false) (bv 32 0x1)))) (! (is_zero (& (>> (var result) (bv 32 0x1f) false) (bv 32 0x1)))))) (branch (var condition) (set PSW (| (& (var PSW) (bv 32 0xefffffff)) (<< (& (ite (var advanced_overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1c) false))) nop) (branch (&& (var condition) (var advanced_overflow)) (set PSW (| (& (var PSW) (bv 32 0xf7ffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1b) false))) nop)) d "mul d0, d0" e200 0x0 (seq (set result (* (var d0) (var d0))) (set d0 (var result)) (set overflow (|| (! (ule (var result) (bv 32 0x7fffffff))) (&& (sle (var result) (bv 32 0x80000000)) (! (== (var result) (bv 32 0x80000000)))))) (set advanced_overflow (^^ (! (is_zero (& (>> (var result) (bv 32 0x1f) false) (bv 32 0x1)))) (! (is_zero (& (>> (var result) (bv 32 0x1e) false) (bv 32 0x1)))))) (set PSW (| (& (var PSW) (bv 32 0xbfffffff)) (<< (& (ite (var overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1e) false))) (set PSW (| (& (var PSW) (bv 32 0xefffffff)) (<< (& (ite (var advanced_overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1c) false))) (branch (var overflow) (set PSW (| (& (var PSW) (bv 32 0xdfffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1d) false))) nop) (branch (var advanced_overflow) (set PSW (| (& (var PSW) (bv 32 0xf7ffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1b) false))) nop)) d "mul d0, d0, #0" 53002000 0x0 (seq (set result (* (var d0) (bv 32 0x0))) (set d0 (var result)) (set overflow (|| (! (ule (var result) (bv 32 0x7fffffff))) (&& (sle (var result) (bv 32 0x80000000)) (! (== (var result) (bv 32 0x80000000)))))) (set advanced_overflow (^^ (! (is_zero (& (>> (var result) (bv 32 0x1f) false) (bv 32 0x1)))) (! (is_zero (& (>> (var result) (bv 32 0x1e) false) (bv 32 0x1)))))) (set PSW (| (& (var PSW) (bv 32 0xbfffffff)) (<< (& (ite (var overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1e) false))) (set PSW (| (& (var PSW) (bv 32 0xefffffff)) (<< (& (ite (var advanced_overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1c) false))) (branch (var overflow) (set PSW (| (& (var PSW) (bv 32 0xdfffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1d) false))) nop) (branch (var advanced_overflow) (set PSW (| (& (var PSW) (bv 32 0xf7ffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1b) false))) nop)) d "mul d0, d0, d0" 73000a00 0x0 (seq (set result (* (var d0) (var d0))) (set d0 (var result)) (set overflow (|| (! (ule (var result) (bv 32 0x7fffffff))) (&& (sle (var result) (bv 32 0x80000000)) (! (== (var result) (bv 32 0x80000000)))))) (set advanced_overflow (^^ (! (is_zero (& (>> (var result) (bv 32 0x1f) false) (bv 32 0x1)))) (! (is_zero (& (>> (var result) (bv 32 0x1e) false) (bv 32 0x1)))))) (set PSW (| (& (var PSW) (bv 32 0xbfffffff)) (<< (& (ite (var overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1e) false))) (set PSW (| (& (var PSW) (bv 32 0xefffffff)) (<< (& (ite (var advanced_overflow) (bv 32 0x1) (bv 32 0x0)) (bv 32 0x1)) (bv 32 0x1c) false))) (branch (var overflow) (set PSW (| (& (var PSW) (bv 32 0xdfffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1d) false))) nop) (branch (var advanced_overflow) (set PSW (| (& (var PSW) (bv 32 0xf7ffffff)) (<< (& (bv 32 0x1) (bv 32 0x1)) (bv 32 0x1b) false))) nop))