tricore: lift remaining floating point instructions (#4514)

* tricore: fix `mfcr` and `mtcr`
* tricore: `ftoi`
* tricore: fix `round_to_integer`
* tricore: tricore_il_fp.inc
* tricore: fix `ftoi` `ftoiz`
* rzil: Add `rz_il_op_new_float_from_rz_float`
* tricore: add `ftoq31`
* tricore: add `ftou`
* tricore: fix `hptof` and `ftohp`
* tricore: set flags and `itof` `q31tof` `utof`
* tricore: add.f sub.f mul.f div.f
* tricore: qseed.f
* tricore: madd.f msub.f
* tricore: add rzil asm tests
* rzil: validate il op when `aoi`
* tricore : add fp emulateme test
This commit is contained in:
billow 2024-06-03 01:36:50 -07:00 committed by GitHub
parent d1a7dbad5d
commit 255f6fdd0f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 2941 additions and 1021 deletions

View file

@ -184,6 +184,11 @@ static const char *TriCoreREGs[] = {
"FPU_TRAP_SRC1",
"FPU_TRAP_SRC2",
"FPU_TRAP_SRC3",
"set_FI",
"set_FV",
"set_FZ",
"set_FU",
"set_FX",
NULL
};
@ -403,7 +408,7 @@ static const char *CR_Table(unsigned addr_offset) {
case 0xA010: return "FPU_TRAP_SRC1";
case 0xA014: return "FPU_TRAP_SRC2";
case 0xA018: return "FPU_TRAP_SRC3";
default: return NULL;
default: break;
}
return NULL;
}
@ -807,91 +812,6 @@ static RzILOpPure *sign_32bit(RzILOpPure *val) {
return MSB(val);
}
// static const ut32 ADD_NAN __attribute__((unused)) = 0x7fc00001;
// static const ut32 DIV_NAN __attribute__((unused)) = 0x7fc00008;
// static const ut32 MUL_NAN __attribute__((unused)) = 0x7fc00002;
// static const ut32 SQRT_NAN __attribute__((unused)) = 0x7fc00004;
//
// static const ut32 HP_MAX_VALUE __attribute__((unused)) = 65504;
// static const ut32 HP_MIN_NORMAL __attribute__((unused)) = 1024 * 16;
static const ut32 HP_NEG_INFINITY = 0xfc00;
static const ut32 HP_POS_INFINITY = 0x7c00;
// static const ut32 NEG_INFINITY __attribute__((unused)) = 0xff800000;
// static const ut32 POS_INFINITY __attribute__((unused)) = 0x7f800000;
static inline RzILOpPure *denorm_to_zero(RzILOpFloat *x) {
return LET("tmp", x,
ITE(AND(FLT(VARLP("tmp"), F32(0.0)), FGT(VARLP("tmp"), F32(powf(-2, -126)))), FNEG(F32(0)),
ITE(AND(FGT(VARLP("tmp"), F32(0)), FLT(VARLP("tmp"), F32(powf(2, -126)))), F32(0),
VARLP("tmp"))));
}
/**
* \brief Convert single precision to a half precision
*
* Convert the contents of data register D[a] from IEEE-754-2008 32-bit single precision floating point to IEEE-754-2008
* 16-bit half precision (data interchange) floating point format. The rounded result is put in data register D[c][15:0].
* D[c][31:16] is set to zero.
*/
static RzAnalysisLiftedILOp ftohp(RzAsmTriCoreContext *ctx) {
const char *a = R(1);
const char *c = R(0);
// if(sign_32bit(D[a])) then {
// D[c][15:0] = HP_NEG_INFINITY;
// } else {
// D[c][15:0] = HP_POS_INFINITY;
// }
RzILOpEffect *inf_eff = BRANCH(sign_32bit(VARG(a)),
SETG(c, U32(HP_NEG_INFINITY)),
SETG(c, U32(HP_POS_INFINITY)));
// D[c][15] = sign_32bit(D[a]);
// D[c][14:10] = 1FH;
// D[c][9:8] = D[a][22:21];
// D[c][7:0] = D[a][7:0];
// Ensure NaN value is preserved
// if ((D[c][9:0] == 0)) then {
// D[c][8] = 1B;
// }
RzILOpPure *dc = LOGAND(VARG(a), U32(1U << 31));
dc = LOGOR(dc, SHL0(U32(0x1f), 10));
dc = LOGOR(dc, SHL0(BITS32(VARG(a), 21, 2), 8));
dc = LOGOR(dc, BITS32(VARG(a), 0, 8));
RzILOpEffect *nan_eff = SEQ2(SETL("D_c", dc),
SETG(c, ITE(EQ(BITS32(VARL("D_c"), 0, 10), U32(0)), BITS32_U(VARL("D_c"), 8, 1, U32(1)), VARL("D_c"))));
// f = denorm_to_zero(D[a]);
// f_rounded = ieee754_round_16bit(f, PSW.RM);
// Handle overflow & underflow and convert to 16-bit format
// D[a][15:0] = ieee754_16bit_format(f_rounded);
RzILOpPure *f = denorm_to_zero(FLOATV32(VARG(a)));
// RzILOpPure *f_rounded = FROUND(/*TODO: PSW_RM()*/ 0, f);
RzILOpEffect *else_eff = SETG(c,
BITS32_U(VARG(a), 0, 16, UNSIGNED(32, F2BV(FCONVERT(RZ_FLOAT_IEEE754_BIN_16, 0, f)))));
return BRANCH(IS_FINF(FLOATV32(VARG(a))), inf_eff,
BRANCH(IS_FNAN(FLOATV32(VARG(a))), nan_eff, else_eff));
}
static RzILOpPure *f_real(RzILOpFloat *x) {
return x;
}
static RzAnalysisLiftedILOp ftoiz(RzAsmTriCoreContext *ctx) {
RzILOpPure *a = VARG(R(1));
const char *cname = R(0);
return SETG(cname,
ITE(IS_FINF(FLOATV32(a)),
U32(0),
ITE(SGT(f_real(DUP(a)), U32(0x7FFFFFFF)), U32(0x7FFFFFFF),
ITE(SLT(f_real(DUP(a)), U32(0x80000000)),
U32(0x80000000),
F2SINT(32, RZ_FLOAT_RMODE_RTZ, DUP(a))))));
}
#define Byte_b 8
#define HalfWord_b 16
#define Word_b 32
@ -940,10 +860,6 @@ static RzILOpPure *reverse16(RzILOpPure *x) {
return reflect(x, 16);
}
static RzILOpPure *is_denorm(RzILOpPure *x) {
return AND(IS_ZERO(BITS32(x, 23, 8)), NON_ZERO(BITS32(DUP(x), 0, 23)));
}
static RzAnalysisLiftedILOp f_cons_(RzILOpEffect *x, RzILOpEffect *y) {
if (!(x && x->code == RZ_IL_OP_SEQ)) {
goto err;
@ -2717,7 +2633,6 @@ static RzAnalysisLiftedILOp f_madd(
RzAnalysisLiftedILOp xs,
const char *name1, const char *name2,
RzILOpPure *a, RzILOpPure *b, unsigned arg_n, unsigned i1, unsigned i2, unsigned n) {
rz_warn_if_fail(arg_n == 1 || arg_n == 0);
Mab(madd_a, madd_b);
f_cons(xs,
@ -2745,7 +2660,6 @@ static RzAnalysisLiftedILOp f_mul(
RzAnalysisLiftedILOp xs,
const char *name1, const char *name2,
RzILOpPure *a, RzILOpPure *b, unsigned arg_n, unsigned i1, unsigned i2, unsigned n) {
rz_warn_if_fail(arg_n == 1 || arg_n == 0);
Mab(mul_a, mul_b);
f_cons(xs,
@ -2761,7 +2675,6 @@ static RzAnalysisLiftedILOp f_mulr(
RzAnalysisLiftedILOp xs,
const char *name1, const char *name2,
RzILOpPure *a, RzILOpPure *b, unsigned arg_n, unsigned i1, unsigned i2, unsigned n) {
rz_warn_if_fail(arg_n == 1 || arg_n == 0);
Mab(mulr_a, mulr_b);
f_cons(xs,
@ -2778,7 +2691,6 @@ static RzAnalysisLiftedILOp f_maddr(
RzAnalysisLiftedILOp xs, RzAsmTriCoreContext *ctx,
const char *name1, const char *name2, const char *name3,
RzILOpPure *a, RzILOpPure *b, unsigned arg_n, unsigned i1, unsigned i2, unsigned n) {
rz_warn_if_fail(arg_n == 1 || arg_n == 0);
xs = f_mul(xs, name1, name2, a, b, arg_n, i1, i2, n);
return f_cons_(xs,
SETL(name3,
@ -3013,6 +2925,8 @@ static RzAnalysisLiftedILOp population_count(
return xs;
}
#include "tricore_il_fp.inc"
RZ_IPI RzAnalysisLiftedILOp tricore_il_op(RzAsmTriCoreContext *ctx, RzAnalysis *a) {
ctx->word = rz_read_le32(ctx->insn->bytes);
switch (ctx->insn->id) {
@ -3025,35 +2939,23 @@ RZ_IPI RzAnalysisLiftedILOp tricore_il_op(RzAsmTriCoreContext *ctx, RzAnalysis *
case TRICORE_INS_FRET: return fret();
case TRICORE_INS_FTOHP: return ftohp(ctx);
case TRICORE_INS_FTOIZ: return ftoiz(ctx);
case TRICORE_INS_FTOI:
case TRICORE_INS_FTOQ31Z:
case TRICORE_INS_FTOQ31:
case TRICORE_INS_FTOUZ:
case TRICORE_INS_FTOU:
case TRICORE_INS_HPTOF:
case TRICORE_INS_ITOF:
case TRICORE_INS_Q31TOF:
case TRICORE_INS_DIV_F:
case TRICORE_INS_ADD_F:
case TRICORE_INS_MADD_F:
case TRICORE_INS_MSUB_F:
case TRICORE_INS_SUB_F:
case TRICORE_INS_MUL_F:
case TRICORE_INS_QSEED_F:
case TRICORE_INS_UTOF: NOT_IMPLEMENTED;
case TRICORE_INS_CMP_F: {
const char *rc = R(0);
const char *ra = R(1);
const char *rb = R(2);
return SETG(rc,
f_op2_chain6(rz_il_op_new_log_or,
BOOL_TO_BV32(FLT(FLOATV32(VARG(ra)), FLOATV32(VARG(rb)))),
SHL0(BOOL_TO_BV32(FEQ(FLOATV32(VARG(ra)), FLOATV32(VARG(rb)))), 1),
SHL0(BOOL_TO_BV32(FGT(FLOATV32(VARG(ra)), FLOATV32(VARG(rb)))), 2),
SHL0(BOOL_TO_BV32(OR(IS_FNAN(FLOATV32(VARG(ra))), IS_FNAN(FLOATV32(VARG(rb))))), 3),
SHL0(BOOL_TO_BV32(is_denorm(VARG(ra))), 4),
SHL0(BOOL_TO_BV32(is_denorm(VARG(rb))), 5)));
}
case TRICORE_INS_FTOI: return ftoi(ctx);
case TRICORE_INS_FTOQ31Z: return ftoq31z(ctx);
case TRICORE_INS_FTOQ31: return ftoq31(ctx);
case TRICORE_INS_FTOUZ: return ftouz(ctx);
case TRICORE_INS_FTOU: return ftou(ctx);
case TRICORE_INS_HPTOF: return hptof(ctx);
case TRICORE_INS_ITOF: return itof(ctx);
case TRICORE_INS_Q31TOF: return q31tof(ctx);
case TRICORE_INS_UTOF: return utof(ctx);
case TRICORE_INS_ADD_F: return add_f(ctx);
case TRICORE_INS_SUB_F: return sub_f(ctx);
case TRICORE_INS_MUL_F: return mul_f(ctx);
case TRICORE_INS_DIV_F: return div_f(ctx);
case TRICORE_INS_MADD_F: return madd_f(ctx);
case TRICORE_INS_MSUB_F: return msub_f(ctx);
case TRICORE_INS_QSEED_F: return qseed_f(ctx);
case TRICORE_INS_CMP_F: return cmp_f(ctx);
case TRICORE_INS_UPDFL: {
RzILOpPure *m = BITS32(VARG(R(0)), 8, 8);
RzILOpPure *v = BITS32(VARG(R(0)), 0, 8);
@ -4066,8 +3968,20 @@ RZ_IPI RzAnalysisLiftedILOp tricore_il_op(RzAsmTriCoreContext *ctx, RzAnalysis *
}
break;
}
case TRICORE_INS_MFCR: return SETG(R(0), VARG(CR_Table(I(1))));
case TRICORE_INS_MTCR: return SETG(CR_Table(I(0)), VARG(R(1)));
case TRICORE_INS_MFCR: {
const char *cr = CR_Table(I(1));
if (!cr) {
return NULL;
}
return SETG(R(0), VARG(cr));
}
case TRICORE_INS_MTCR: {
const char *cr = CR_Table(I(0));
if (!cr) {
return NULL;
}
return SETG(cr, VARG(R(1)));
}
case TRICORE_INS_BMERGE:
return SETG(R(0),
APPEND(

View file

@ -68,17 +68,17 @@ static inline RzILOpPure *BITS32_U(RzILOpPure *val, ut32 i, ut32 n, RzILOpPure *
}
// ((value >> start) & (~0ULL >> (0x20 - length)))
static ut32 extract32(ut32 x, ut32 start, ut32 len) {
static inline ut32 extract32(ut32 x, ut32 start, ut32 len) {
return (x >> start) & (~0U >> (0x20 - len));
}
static RzILOpPure *SEXT32(RzILOpPure *value, ut32 length) {
static inline RzILOpPure *SEXT32(RzILOpPure *value, ut32 length) {
return LET("_sext_val", SIGNED(32, value), rz_il_sextract32(VARLP("_sext_val"), U32(0), U32(length)));
}
static RzILOpPure *SEXT64(RzILOpPure *value, ut32 length) {
static inline RzILOpPure *SEXT64(RzILOpPure *value, ut32 length) {
return LET("_sext_val", SIGNED(32, value), rz_il_sextract64(VARLP("_sext_val"), U32(0), U32(length)));
}
static RzILOpPure *ZEXT32(RzILOpPure *value, ut32 length) {
static inline RzILOpPure *ZEXT32(RzILOpPure *value, ut32 length) {
return value;
}
static inline RzILOpPure *SHL0(RzILOpPure *value, ut32 length) {
@ -235,4 +235,7 @@ REG_FIELD(TASK_ASI, ASI, 0, 5);
#undef REG_FIELD_VERS
#undef REG_FIELD_VER
RZ_IPI RzAnalysisLiftedILOp tricore_il_op(RzAsmTriCoreContext *ctx, RzAnalysis *a);
RZ_IPI RzAnalysisILConfig *tricore_il_config(RZ_NONNULL RzAnalysis *analysis);
#endif // RIZIN_TRICORE_IL_H

View file

@ -0,0 +1,602 @@
// SPDX-FileCopyrightText: 2024 billow <billow.fun@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
/// The maximum of IEEE-754-2008 16-bit half precision floating point
static const ut32 HP_MAX_VALUE = 65504;
/// The minimum positive normalized number of IEEE-754-2008 16-bit half precision floating point
static const ut32 HP_MIN_NORMAL = 1024 * 16;
/// This represents all positive numbers that are too big to be represented accurately as a normalized number.
static const ut32 HP_NEG_INFINITY = 0xfc00;
/// This represents all negative numbers with an absolute value that is too big to be represented accurately as a normalized number.
static const ut32 HP_POS_INFINITY = 0x7c00;
#define F2SINT32(x, m) F2SINT(32, m, x)
#define denorm_to_zere_(T, x) \
LET("tmp", x, \
ITE(AND(FLT(VARLP("tmp"), T(0.0)), FGT(VARLP("tmp"), T(powf(-2, -126)))), FNEG(T(0)), \
ITE(AND(FGT(VARLP("tmp"), T(0)), FLT(VARLP("tmp"), T(powf(2, -126)))), T(0), \
VARLP("tmp"))))
#define denorm_to_zere64(x) denorm_to_zere_(F64, x)
#define F6432(x) FCONVERT(RZ_FLOAT_IEEE754_BIN_32, 0, x)
#define F3264(x) FCONVERT(RZ_FLOAT_IEEE754_BIN_64, 0, x)
#define _32F64(x) F3264(FLOATV32(x))
#define i32F32(x) SINT2F(RZ_FLOAT_IEEE754_BIN_32, 0, x)
#define i32F64(x) F3264(i32F32(x))
static inline RzILOpPure *is_denorm(RzILOpPure *x) {
return AND(IS_ZERO(BITS32(x, 23, 8)), NON_ZERO(BITS32(DUP(x), 0, 23)));
}
/**
* \brief Returns the Q31 format value x as an infinitely accurate real value.
*/
static inline RzILOpFloat *q_real(ut32 x) {
float y = x & 0x80000000 ? -1.f : 0.f;
for (int i = 0; i < 31; ++i) {
ut32 m = 1u << (30 - i);
float b = 1.f / (float)(2u << i);
if (x & m) {
y += b;
}
}
RzFloat *value = rz_float_new_from_f32(y);
if (!value) {
return NULL;
}
return rz_il_op_new_float_from_rz_float(value);
}
static inline RzILOpEffect *q_real_set_v(const char *k, RzILOpPure *x) {
return SEQ4(
SETL("_x", x),
SETL("_i", U32(0)),
SETL(k, ITE(MSB(VARL("_x")), F32(-1.), F32(0.f))),
REPEAT(
ULT(VARL("_i"), U32(31)),
SEQ4(
SETL("_i", ADD(VARL("_i"), U32(1))),
SETL("_m", SHIFTL0(U32(1), SUB(U32(30), VARL("_i")))),
SETL("_b", FDIV(RZ_FLOAT_RMODE_RNE, F32(1.f), FLOATV32(SHIFTL0(U32(2), VARL("_i"))))),
BRANCH(
NON_ZERO(LOGAND(VARL("_x"), VARL("_m"))),
SETL(k, FADD(0, VARL(k), VARL("_b"))),
NOP()))));
}
#define FCAST_(f, _1, x, mode, _default) \
LET("_mode", UNSIGNED(8, mode), \
LET("_x", x, \
ITE(EQ(VARLP("_mode"), U8(0)), \
f(_1, RZ_FLOAT_RMODE_RNE, VARLP("_x")), \
ITE(EQ(VARLP("_mode"), U8(1)), \
f(_1, RZ_FLOAT_RMODE_RNA, VARLP("_x")), \
ITE(EQ(VARLP("_mode"), U8(2)), \
f(_1, RZ_FLOAT_RMODE_RTN, VARLP("_x")), \
ITE(EQ(VARLP("_mode"), U8(3)), \
f(_1, RZ_FLOAT_RMODE_RTP, VARLP("_x")), \
ITE(EQ(VARLP("_mode"), U8(4)), \
f(_1, RZ_FLOAT_RMODE_RTZ, VARLP("_x")), \
_default)))))))
#define FCAST32(f, _1, x, mode) FCAST_(f, _1, x, mode, F32(0))
#define FCAST64(f, _1, x, mode) FCAST_(f, _1, x, mode, F64(0))
#define round_to_integer(x, m) FCAST_(F2SINT, 32, x, m, U32(UT32_MAX))
static RzILOpPure *minmax(const char *k, st64 min, st64 max, RzILOpPure *x) {
return ITE(IS_FNAN(VARL(k)),
U32(0),
ITE(FGT(VARL(k), F64(max)),
U32(max),
ITE(FLT(VARL(k), F64(min)),
U32(min),
x)));
}
// The maximum of the Q31 format value
#define Q31_MAX q_real(0x7FFFFFFF)
// The minimum of the Q31 format value
#define Q31_MIN F32(-1.f)
static RzILOpPure *minmax_q31(const char *k, RzILOpPure *x) {
return ITE(FGT(VARL(k), q_real(0x7FFFFFFF)),
U32(0x7FFFFFFF),
ITE(FLT(VARL(k), F32(-1.0)),
U32(0x80000000),
x));
}
#define not_in(x, min, max) OR(FGT(x, max), FLT(DUP(x), min))
#define not_in_q31(x) not_in(x, Q31_MIN, Q31_MAX)
#define not_in_u32(x) not_in(x, F64(0.f), F64(UT32_MAX))
#define not_in_i32(x) not_in(x, F64(ST32_MIN), F64(ST32_MAX))
#define set_FPU_s(k, x) SETG("set_" #k, x)
#define set_FPU(k, x) SEQ2( \
SETG("set_" #k, x), \
BRANCH(VARG("set_" #k), set_PSW_##k(U32(1)), NOP()))
static RzILOpPure *ieee754_16bit_underflow(RzILOpPure *x) {
return AND(FLT(x, FLOATV32(U32(HP_MIN_NORMAL))), FGT(DUP(x), F32(0)));
}
static RzILOpPure *ieee754_16bit_overflow(RzILOpFloat *x) {
return FGT(x, FLOATV32(U32(HP_MAX_VALUE)));
}
#define set_PSW_FSb(x) set_PSW_FS(BOOL_TO_BV32(x))
#define set_FS_or_FI_FV_FU_FX set_PSW_FSb(f_op2_chain4(rz_il_op_new_bool_or, VARG("set_FI"), VARG("set_FV"), VARG("set_FU"), VARG("set_FX")))
/**
* \brief Convert single precision to a half precision
*
* Convert the contents of data register D[a] from IEEE-754-2008 32-bit single precision floating point to IEEE-754-2008
* 16-bit half precision (data interchange) floating point format. The rounded result is put in data register D[c][15:0].
* D[c][31:16] is set to zero.
*/
static RzAnalysisLiftedILOp ftohp(RzAsmTriCoreContext *ctx) {
const char *a = R(1);
const char *c = R(0);
// if(sign_32bit(D[a])) then {
// D[c][15:0] = HP_NEG_INFINITY;
// } else {
// D[c][15:0] = HP_POS_INFINITY;
// }
RzILOpEffect *inf_eff = BRANCH(sign_32bit(VARG(a)),
SETG(c, U32(HP_NEG_INFINITY)),
SETG(c, U32(HP_POS_INFINITY)));
// D[c][15] = sign_32bit(D[a]);
// D[c][14:10] = 1FH;
// D[c][9:8] = D[a][22:21];
// D[c][7:0] = D[a][7:0];
// Ensure NaN value is preserved
// if ((D[c][9:0] == 0)) then {
// D[c][8] = 1B;
// }
RzILOpPure *dc = LOGAND(VARG(a), U32(1U << 31));
dc = LOGOR(dc, SHL0(U32(0x1f), 10));
dc = LOGOR(dc, SHL0(BITS32(VARG(a), 21, 2), 8));
dc = LOGOR(dc, BITS32(VARG(a), 0, 8));
RzILOpEffect *nan_eff = SEQ2(SETL("D_c", dc),
SETG(c, ITE(EQ(BITS32(VARL("D_c"), 0, 10), U32(0)), BITS32_U(VARL("D_c"), 8, 1, U32(1)), VARL("D_c"))));
// f = denorm_to_zero(D[a]);
// f_rounded = ieee754_round_16bit(f, PSW.RM);
// Handle overflow & underflow and convert to 16-bit format
// D[a][15:0] = ieee754_16bit_format(f_rounded);
RzILOpEffect *else_eff =
SEQ3(SETL("_fa", denorm_to_zere64(FLOATV32(VARG(a)))),
SETL("_f_rounded", FCAST32(FCONVERT, RZ_FLOAT_IEEE754_BIN_16, VARL("_fa"), PSW_RM())),
SETG(c, BITS32_U(VARG(c), 0, 16, UNSIGNED(32, VARL("_f_rounded")))));
RzILOpEffect *set_status = SEQ5(
set_FPU(FX, FNE(VARL("_fa"), FLOATV32(UNSIGNED(16, VARG(R(1)))))),
set_FPU(FU, AND(ieee754_16bit_underflow(VARL("_fa")), VARG("set_FX"))),
set_FPU(FV, ieee754_16bit_overflow(VARL("_fa"))),
set_FPU(FI, IS_FNAN(VARG(R(1)))),
set_FS_or_FI_FV_FU_FX);
return SEQ4(
SETL("_fa", F32(0)),
SETL("_f_rounded", F32(0)),
BRANCH(IS_FINF(FLOATV32(VARG(a))), inf_eff,
BRANCH(IS_FNAN(FLOATV32(VARG(a))), nan_eff, else_eff)),
set_status);
}
/**
* HPTOF D[c], D[a] (RR)
* hp = D[a][15:0];
* if (is_inf_16bit(hp)) then {
* // Signed Infinity
* if(sign_16bit(hp)) then {
* D[c][31:0] = NEG_INFINITY;
* } else {
* D[c][31:0] = POS_INFINITY;
* }
* } else if (is_nan_16bit(hp)) then {
* // Signed NaN
* D[c][31] = sign_16bit(hp);
* D[c][30:23] = FFH;
* D[c][22:21] = D[a][9:8];
* D[c][20:8] = 0;
* D[c][7:0] = D[a][7:0];
* } else {
* f = f_real_16bit(hp);
* D[c] = ieee754_32bit_format(f);
* }
*/
static RzAnalysisLiftedILOp hptof(RzAsmTriCoreContext *ctx) {
return SEQ4(
SETL("_hp", UNSIGNED(16, VARG(R(1)))),
SETL("_result", FCONVERT(RZ_FLOAT_IEEE754_BIN_32, RZ_FLOAT_RMODE_RNA, FLOATV16(VARL("_hp")))),
SETG(R(0), F2BV(VARL("_result"))),
SEQ2(set_FPU(FI, IS_FNAN(VARL("_hp"))),
set_PSW_FSb((VARG("set_FI")))));
}
/**
* D[c], D[a] (RR)
* if(is_nan(D[a])) then result = 0;
* else if(f_real(D[a]) > 2^31-1) then result = 7FFFFFFFH;
* else if(f_real(D[a]) < -2^31) then result = 80000000H;
* else result = round_to_integer(D[a], PSW.RM);
* D[c] = result[31:0];
*/
static RzAnalysisLiftedILOp ftoi(RzAsmTriCoreContext *ctx) {
return SEQ4(
SETL("_fa", _32F64(VARG(R(1)))),
SETL("_result_i", minmax("_fa", ST32_MAX, ST32_MIN, round_to_integer(VARL("_fa"), PSW_RM()))),
SETG(R(0), VARL("_result_i")),
SEQ3(set_FPU(FI, OR(not_in_i32(VARL("_fa")), IS_FNAN(VARL("_fa")))),
set_FPU(FX, FNE(VARL("_fa"), i32F64(VARL("_result_i")))),
set_PSW_FSb(OR(VARG("set_FX"), VARG("set_FI")))));
}
/**
* FTOIZ D[c], D[a] (RR)
* if(is_nan(D[a])) then result = 0;
* else if(f_real(D[a]) > 2^31-1) then result = 7FFFFFFFH;
* else if(f_real(D[a]) < -2^31) then result = 80000000H;
* else result = round_to_integer(D[a], 11B);
* D[c] = result[31:0];
*/
static RzAnalysisLiftedILOp ftoiz(RzAsmTriCoreContext *ctx) {
return SEQ4(
SETL("_fa", _32F64(VARG(R(1)))),
SETL("_result_i", minmax("_fa", ST32_MAX, ST32_MIN, F2SINT32(VARL("_fa"), RZ_FLOAT_RMODE_RTZ))),
SETG(R(0), VARL("_result_i")),
SEQ3(set_FPU(FI, OR(not_in_u32(VARL("_fa")), IS_FNAN(VARL("_fa")))),
set_FPU(FX, FNE(VARL("_fa"), i32F64(VARL("_result_i")))),
set_PSW_FSb((OR(VARG("set_FX"), VARG("set_FI"))))));
}
/**
* D[c], D[a] (RR)
*
* rounded_result = ieee754_round(i_real(D[a]), PSW.RM);
* result = ieee754_32bit_format(rounded_result);
* D[c] = result[31:0];
*/
static RzAnalysisLiftedILOp itof(RzAsmTriCoreContext *ctx) {
return SEQ6(
SETL("_a", VARG(R(1))),
SETL("_result64", FCAST64(SINT2F, RZ_FLOAT_IEEE754_BIN_64, VARL("_a"), PSW_RM())),
SETL("_result32", FCAST32(SINT2F, RZ_FLOAT_IEEE754_BIN_32, VARL("_a"), PSW_RM())),
SETL("_result32_64", FCAST64(FCONVERT, RZ_FLOAT_IEEE754_BIN_64, VARL("_result32"), PSW_RM())),
SETG(R(0), F2BV(VARL("_result32"))),
SEQ2(set_FPU(FX, FNE(VARL("_result32_64"), VARL("_result64"))),
set_PSW_FSb((VARG("set_FX")))));
}
static RzAnalysisLiftedILOp ftou(RzAsmTriCoreContext *ctx) {
return SEQ4(
SETL("_fa", _32F64(VARG(R(1)))),
SETL("_result_i", minmax("_fa", UT32_MAX, UT32_MIN, round_to_integer(VARL("_fa"), PSW_RM()))),
SETG(R(0), VARL("_result_i")),
SEQ3(set_FPU(FI, OR(not_in_u32(VARL("_fa")), IS_FNAN(VARL("_fa")))),
set_FPU(FX, FNE(VARL("_fa"), i32F64(VARL("_result_i")))),
set_PSW_FSb(OR(VARG("set_FX"), VARG("set_FI")))));
}
static RzAnalysisLiftedILOp ftouz(RzAsmTriCoreContext *ctx) {
return SEQ4(
SETL("_fa", _32F64(VARG(R(1)))),
SETL("_result_i", minmax("_fa", UT32_MAX, UT32_MIN, F2SINT32(VARL("_fa"), RZ_FLOAT_RMODE_RTZ))),
SETG(R(0), VARL("_result_i")),
SEQ3(set_FPU(FI, OR(not_in_u32(VARL("_fa")), IS_FNAN(VARL("_fa")))),
set_FPU(FX, FNE(VARL("_fa"), i32F64(VARL("_result_i")))),
set_PSW_FSb(OR(VARG("set_FX"), VARG("set_FI")))));
}
static RzAnalysisLiftedILOp utof(RzAsmTriCoreContext *ctx) {
return SEQ4(
SETL("_a", VARG(R(1))),
SETL("_result", FCAST32(INT2F, RZ_FLOAT_IEEE754_BIN_32, VARL("_a"), PSW_RM())),
SETG(R(0), F2BV(VARL("_result"))),
SEQ2(set_FPU(FX, FNE(i32F32(VARL("_a")), VARL("_result"))),
set_PSW_FSb(VARG("set_FX"))));
}
/**
* FTOQ31 D[c], D[a], D[b] (RR)
* arg_a = denorm_to_zere64(f_real(D[a]);
* if(is_nan(D[a])) then result = 0;
* else precise_result = mul(arg_a, 2^-D[b][8:0]);
* if(precise_result > q_real(7FFFFFFFH)) then result = 7FFFFFFFH;
* else if(precise_result < -1.0) then result = 80000000H;
* else result = round_to_q31(precise_result);
* D[c] = result[31:0];
*/
static RzAnalysisLiftedILOp ftoq31(RzAsmTriCoreContext *ctx) {
return SEQ8(
SETL("_a", VARG(R(1))),
SETL("_arg_a", F32(0)),
q_real_set_v("_arg_a", VARL("_a")),
SETL("_arg_a", denorm_to_zere_(F32, VARL("_arg_a"))),
SETL("_precise_result", FDIV(0, VARL("_arg_a"), FPOW(0, F32(2), FLOATV32(LOGAND(VARG(R(2)), U32(0x1ff)))))),
SETL("_result_i",
ITE(IS_FNAN(FLOATV32(VARL("_a"))),
U32(0),
minmax_q31("_precise_result", round_to_integer(VARL("_precise_result"), PSW_RM())))),
SETG(R(0), VARL("_result_i")),
SEQ5(SETL("_res_q_real", F32(0)),
q_real_set_v("_res_q_real", VARL("_result_i")),
set_FPU(FI, OR(not_in_q31(VARL("_precise_result")), IS_FNAN(FLOATV32(VARL("_a"))))),
set_FPU(FX, FNE(FLOATV32(VARL("_a")), VARL("_res_q_real"))),
set_PSW_FSb(OR(VARG("set_FX"), VARG("set_FI")))));
}
static RzAnalysisLiftedILOp ftoq31z(RzAsmTriCoreContext *ctx) {
return SEQ9(
SETL("_a", VARG(R(1))),
SETL("_fa", FLOATV32(VARL("_a"))),
SETL("_arg_a", F32(0)),
q_real_set_v("_arg_a", VARL("_a")),
SETL("_arg_a", denorm_to_zere_(F32, VARL("_arg_a"))),
SETL("_precise_result", FDIV(0, VARL("_arg_a"), FPOW(0, F32(2), FLOATV32(LOGAND(VARG(R(2)), U32(0x1ff)))))),
SETL("_result_i",
ITE(IS_FNAN(VARL("_fa")),
U32(0),
minmax_q31("_precise_result", F2SINT32(VARL("_precise_result"), RZ_FLOAT_RMODE_RTZ)))),
SETG(R(0), VARL("_result_i")),
SEQ5(SETL("_res_q_real", F32(0)),
q_real_set_v("_res_q_real", VARL("_result_i")),
set_FPU(FI, OR(not_in_q31(VARL("_precise_result")), IS_FNAN(FLOATV32(VARL("_a"))))),
set_FPU(FX, FNE(VARL("_fa"), VARL("_res_q_real"))),
set_PSW_FSb(OR(VARG("set_FX"), VARG("set_FI")))));
}
/**
* Q31TOF D[c], D[a], D[b] (RR)
*
* precise_result = mul(q_real(D[a]),2^D[b][8:0]);
* rounded_result = ieee754_round(precise_result, PSW.RM);
* result = ieee754_32bit_format(rounded_result);
* D[c] = result[31:0];
*/
static RzAnalysisLiftedILOp q31tof(RzAsmTriCoreContext *ctx) {
return SEQ7(
SETL("_a", VARG(R(1))),
SETL("_qa", F32(0)),
q_real_set_v("_qa", VARL("_a")),
SETL("_precise_result", FMUL(RZ_FLOAT_RMODE_RNE, VARL("_qa"), FPOW(0, F32(2.), FLOATV32(LOGAND(VARG(R(2)), U32(0x1ff)))))),
SETL("_result", FCAST32(FCONVERT, RZ_FLOAT_IEEE754_BIN_32, VARL("_precise_result"), PSW_RM())),
SETG(R(0), F2BV(VARL("_result"))),
SEQ3(set_FPU(FX, FNE(VARL("_precise_result"), VARL("_result"))),
set_FPU(FU, FLT(FABS(VARL("_precise_result")), F32(1. / 0x2p126))),
set_PSW_FSb(VARG("set_FX"))));
}
static RzAnalysisLiftedILOp cmp_f(RzAsmTriCoreContext *ctx) {
const char *rc = R(0);
const char *ra = R(1);
const char *rb = R(2);
return SETG(rc,
f_op2_chain6(rz_il_op_new_log_or,
BOOL_TO_BV32(FLT(FLOATV32(VARG(ra)), FLOATV32(VARG(rb)))),
SHL0(BOOL_TO_BV32(FEQ(FLOATV32(VARG(ra)), FLOATV32(VARG(rb)))), 1),
SHL0(BOOL_TO_BV32(FGT(FLOATV32(VARG(ra)), FLOATV32(VARG(rb)))), 2),
SHL0(BOOL_TO_BV32(OR(IS_FNAN(FLOATV32(VARG(ra))), IS_FNAN(FLOATV32(VARG(rb))))), 3),
SHL0(BOOL_TO_BV32(is_denorm(VARG(ra))), 4),
SHL0(BOOL_TO_BV32(is_denorm(VARG(rb))), 5)));
}
#define SEQ10(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9) SEQN(10, e0, e1, e2, e3, e4, e5, e6, e7, e8, e9)
/**
* ADD.F D[c], D[d], D[a] (RRR)
* arg_a = denorm_to_zere64(f_real(D[a]);
* arg_b = denorm_to_zere64(f_real(D[d]);
* if(is_nan(D[a]) OR is_nan(D[d])) then result = QUIET_NAN;
* else if(is_pos_inf(D[a]) AND is_neg_inf(D[d])) then result = ADD_NAN;
* else if(is_neg_inf(D[a]) AND is_pos_inf(D[d])) then result = ADD_NAN;
* else {
* precise_result = add(arg_a,arg_b);
* normal_result = denorm_to_zere64(precise_result);
* rounded_result = ieee754_round(normal_result, PSW.RM);
* result = ieee754_32bit_format(rounded_result);
* }
* D[c] = result[31:0];
*/
static RzAnalysisLiftedILOp add_f(RzAsmTriCoreContext *ctx) {
RzAnalysisLiftedILOp set_status = SEQ6(
set_FPU(FI, OR(IS_FNAN(VARL("_fa")), IS_FNAN(VARL("_fb")))),
set_FPU(FV, FGE(VARL("_rounded_result"), F32(0x2p128))),
set_FPU(FU, FLT(FABS(VARL("_precise_result")), F64(0x2p-126))),
set_FPU_s(FX, FNE(VARL("_precise_result"), FCONVERT(RZ_FLOAT_IEEE754_BIN_64, 0, VARL("_result")))),
set_PSW_FX(BOOL_TO_BV32(AND(VARG("set_FX"), INV(VARG("set_FI"))))),
set_FS_or_FI_FV_FU_FX);
return SEQ10(
SETL("_fa", _32F64(VARG(R(1)))),
SETL("_fb", _32F64(VARG(R(2)))),
SETL("_arg_a", denorm_to_zere64(VARL("_fa"))),
SETL("_arg_b", denorm_to_zere64(VARL("_fb"))),
SETL("_precise_result", FADD(0, VARL("_arg_a"), VARL("_arg_b"))),
SETL("_normal_result", denorm_to_zere64(VARL("_precise_result"))),
SETL("_rounded_result", FCAST32(FCONVERT, RZ_FLOAT_IEEE754_BIN_32, VARL("_normal_result"), PSW_RM())),
SETL("_result",
ITE(OR(IS_FNAN(VARL("_fa")), IS_FNAN(VARL("_fb"))),
IL_FQNAN(RZ_FLOAT_IEEE754_BIN_32),
ITE(AND(IS_FINF(VARL("_fa")), IS_FINF(VARL("_fb"))),
IL_FSNAN(RZ_FLOAT_IEEE754_BIN_32),
VARL("_rounded_result")))),
SETG(R(0), F2BV(VARL("_result"))),
set_status);
}
static RzAnalysisLiftedILOp sub_f(RzAsmTriCoreContext *ctx) {
RzAnalysisLiftedILOp set_status = SEQ6(
set_FPU(FI, OR(IS_FNAN(VARL("_fa")), IS_FNAN(VARL("_fb")))),
set_FPU(FV, FGE(VARL("_rounded_result"), F32(0x2p128))),
set_FPU(FU, FLT(FABS(VARL("_precise_result")), F64(0x2p-126))),
set_FPU_s(FX, FNE(VARL("_precise_result"), FCONVERT(RZ_FLOAT_IEEE754_BIN_64, 0, VARL("_result")))),
set_PSW_FX(BOOL_TO_BV32(AND(VARG("set_FX"), INV(VARG("set_FI"))))),
set_FS_or_FI_FV_FU_FX);
return SEQ10(
SETL("_fa", _32F64(VARG(R(1)))),
SETL("_fb", _32F64(VARG(R(2)))),
SETL("_arg_a", denorm_to_zere64(VARL("_fa"))),
SETL("_arg_b", denorm_to_zere64(VARL("_fb"))),
SETL("_precise_result", FADD(0, FNEG(VARL("_arg_a")), VARL("_arg_b"))),
SETL("_normal_result", denorm_to_zere64(VARL("_precise_result"))),
SETL("_rounded_result", FCAST32(FCONVERT, RZ_FLOAT_IEEE754_BIN_32, VARL("_normal_result"), PSW_RM())),
SETL("_result",
ITE(OR(IS_FNAN(VARL("_fa")), IS_FNAN(VARL("_fb"))),
IL_FQNAN(RZ_FLOAT_IEEE754_BIN_32),
ITE(AND(IS_FINF(VARL("_fa")), IS_FINF(VARL("_fb"))),
IL_FSNAN(RZ_FLOAT_IEEE754_BIN_32),
VARL("_rounded_result")))),
SETG(R(0), F2BV(VARL("_result"))),
set_status);
}
static RzAnalysisLiftedILOp mul_f(RzAsmTriCoreContext *ctx) {
RzAnalysisLiftedILOp set_status = SEQ6(
set_FPU(FI, OR(OR(IS_FNAN(VARL("_fa")), IS_FNAN(VARL("_fb"))), IS_FNAN(VARL("_result")))),
set_FPU(FV, FGE(VARL("_rounded_result"), F32(0x2p128))),
set_FPU(FU, FLT(FABS(VARL("_precise_result")), F64(0x2p-126))),
set_FPU_s(FX, FNE(VARL("_precise_result"), FCONVERT(RZ_FLOAT_IEEE754_BIN_64, 0, VARL("_result")))),
set_PSW_FX(BOOL_TO_BV32(AND(VARG("set_FX"), INV(VARG("set_FI"))))),
set_FS_or_FI_FV_FU_FX);
return SEQ10(
SETL("_fa", _32F64(VARG(R(1)))),
SETL("_fb", _32F64(VARG(R(2)))),
SETL("_arg_a", denorm_to_zere64(VARL("_fa"))),
SETL("_arg_b", denorm_to_zere64(VARL("_fb"))),
SETL("_precise_result", FMUL(0, VARL("_arg_a"), VARL("_arg_b"))),
SETL("_normal_result", denorm_to_zere64(VARL("_precise_result"))),
SETL("_rounded_result", FCAST32(FCONVERT, RZ_FLOAT_IEEE754_BIN_32, VARL("_normal_result"), PSW_RM())),
SETL("_result",
ITE(OR(IS_FNAN(VARL("_fa")), IS_FNAN(VARL("_fb"))),
IL_FQNAN(RZ_FLOAT_IEEE754_BIN_32),
ITE(OR(AND(IS_FINF(VARL("_fa")), IS_FZERO(VARL("_fb"))),
AND(IS_FZERO(VARL("_fa")), IS_FINF(VARL("_fb")))),
IL_FSNAN(RZ_FLOAT_IEEE754_BIN_32),
VARL("_rounded_result")))),
SETG(R(0), F2BV(VARL("_result"))),
set_status);
}
static RzAnalysisLiftedILOp div_f(RzAsmTriCoreContext *ctx) {
RzAnalysisLiftedILOp set_status = SEQ7(
set_FPU(FI, OR(OR(IS_FNAN(VARL("_fa")), IS_FNAN(VARL("_fb"))), IS_FNAN(VARL("_result")))),
set_FPU(FV, FGE(VARL("_rounded_result"), F32(0x2p128))),
set_FPU(FZ, AND(IS_FZERO(VARL("_fb")), INV(IS_FINF(VARL("_fa"))))),
set_FPU(FU, FLT(FABS(VARL("_precise_result")), F64(0x2p-126))),
set_FPU_s(FX, FNE(VARL("_precise_result"), FCONVERT(RZ_FLOAT_IEEE754_BIN_64, 0, VARL("_result")))),
set_PSW_FX(BOOL_TO_BV32(AND(VARG("set_FX"), INV(VARG("set_FI"))))),
set_FS_or_FI_FV_FU_FX);
return SEQ10(
SETL("_fa", _32F64(VARG(R(1)))),
SETL("_fb", _32F64(VARG(R(2)))),
SETL("_arg_a", denorm_to_zere64(VARL("_fa"))),
SETL("_arg_b", denorm_to_zere64(VARL("_fb"))),
SETL("_precise_result", FDIV(0, VARL("_arg_a"), VARL("_arg_b"))),
SETL("_normal_result", denorm_to_zere64(VARL("_precise_result"))),
SETL("_rounded_result", FCAST32(FCONVERT, RZ_FLOAT_IEEE754_BIN_32, VARL("_normal_result"), PSW_RM())),
SETL("_result",
ITE(OR(IS_FNAN(VARL("_fa")), IS_FNAN(VARL("_fb"))),
IL_FQNAN(RZ_FLOAT_IEEE754_BIN_32),
ITE(OR(AND(IS_FINF(VARL("_fa")), IS_FINF(VARL("_fb"))),
AND(IS_FZERO(VARL("_fa")), IS_FZERO(VARL("_fb")))),
IL_FSNAN(RZ_FLOAT_IEEE754_BIN_32),
VARL("_rounded_result")))),
SETG(R(0), F2BV(VARL("_result"))),
set_status);
}
static RzAnalysisLiftedILOp qseed_f(RzAsmTriCoreContext *ctx) {
RzAnalysisLiftedILOp set_status = SEQ2(
set_FPU(FI, OR(IS_FNAN(VARL("_fa")), IS_FNAN(VARL("_result")))),
set_PSW_FSb(VARG("set_FI")));
return SEQ6(
SETL("_fa", _32F64(VARG(R(1)))),
SETL("_arg_a", denorm_to_zere64(VARL("_fa"))),
SETL("_normal_result", FCAST32(FCONVERT, RZ_FLOAT_IEEE754_BIN_32, FRSQRT(0, VARL("_arg_a")), PSW_RM())),
SETL("_result",
ITE(IS_FZERO(VARL("_arg_a")),
F32(0),
ITE(FLT(VARL("_fa"), F64(0)),
IL_FSNAN(RZ_FLOAT_IEEE754_BIN_32),
VARL("_normal_result")))),
SETG(R(0), F2BV(VARL("_result"))),
set_status);
}
static RzAnalysisLiftedILOp madd_f(RzAsmTriCoreContext *ctx) {
RzAnalysisLiftedILOp set_status = SEQ6(
set_FPU(FI, OR(OR(OR(IS_FNAN(VARL("_fa")), IS_FNAN(VARL("_fb"))), IS_FNAN(VARL("_fc"))), IS_FNAN(VARL("_result")))),
set_FPU(FV, FGE(VARL("_rounded_result"), F32(0x2p128))),
set_FPU(FU, FLT(FABS(VARL("_precise_result")), F64(0x2p-126))),
set_FPU_s(FX, FNE(VARL("_precise_result"), FCONVERT(RZ_FLOAT_IEEE754_BIN_64, 0, VARL("_result")))),
set_PSW_FX(BOOL_TO_BV32(AND(VARG("set_FX"), INV(VARG("set_FI"))))),
set_FS_or_FI_FV_FU_FX);
return SEQN(12,
SETL("_fa", _32F64(VARG(R(1)))),
SETL("_fb", _32F64(VARG(R(2)))),
SETL("_fc", _32F64(VARG(R(3)))),
SETL("_arg_a", denorm_to_zere64(VARL("_fa"))),
SETL("_arg_b", denorm_to_zere64(VARL("_fb"))),
SETL("_arg_c", denorm_to_zere64(VARL("_fc"))),
SETL("_precise_mul_result", FMUL(0, VARL("_arg_a"), VARL("_arg_b"))),
SETL("_precise_result", FADD(0, VARL("_precise_mul_result"), VARL("_arg_c"))),
SETL("_normal_result", denorm_to_zere64(VARL("_precise_result"))),
SETL("_rounded_result", FCAST32(FCONVERT, RZ_FLOAT_IEEE754_BIN_32, VARL("_normal_result"), PSW_RM())),
SETL("_result",
ITE(OR(OR(IS_FNAN(VARL("_fa")), IS_FNAN(VARL("_fb"))), IS_FNAN(VARL("_fc"))),
IL_FQNAN(RZ_FLOAT_IEEE754_BIN_32),
ITE(OR(OR(AND(IS_FINF(VARL("_fa")), IS_FZERO(VARL("_fb"))),
AND(IS_FZERO(VARL("_fa")), IS_FINF(VARL("_fb")))),
AND(AND(IS_FINF(VARL("_fa")), IS_FINF(VARL("_fa"))),
IS_FINF(VARL("_fc")))),
IL_FSNAN(RZ_FLOAT_IEEE754_BIN_32),
VARL("_rounded_result")))),
SETG(R(0), F2BV(VARL("_result"))),
set_status);
}
static RzAnalysisLiftedILOp msub_f(RzAsmTriCoreContext *ctx) {
RzAnalysisLiftedILOp set_status = SEQ6(
set_FPU(FI, OR(OR(OR(IS_FNAN(VARL("_fa")), IS_FNAN(VARL("_fb"))), IS_FNAN(VARL("_fc"))), IS_FNAN(VARL("_result")))),
set_FPU(FV, FGE(VARL("_rounded_result"), F32(0x2p128))),
set_FPU(FU, FLT(FABS(VARL("_precise_result")), F64(0x2p-126))),
set_FPU_s(FX, FNE(VARL("_precise_result"), FCONVERT(RZ_FLOAT_IEEE754_BIN_64, 0, VARL("_result")))),
set_PSW_FX(BOOL_TO_BV32(AND(VARG("set_FX"), INV(VARG("set_FI"))))),
set_FS_or_FI_FV_FU_FX);
return SEQN(12,
SETL("_fa", _32F64(VARG(R(1)))),
SETL("_fb", _32F64(VARG(R(2)))),
SETL("_fc", _32F64(VARG(R(3)))),
SETL("_arg_a", denorm_to_zere64(VARL("_fa"))),
SETL("_arg_b", denorm_to_zere64(VARL("_fb"))),
SETL("_arg_c", denorm_to_zere64(VARL("_fc"))),
SETL("_precise_mul_result", FMUL(0, VARL("_arg_a"), VARL("_arg_b"))),
SETL("_precise_result", FADD(0, FNEG(VARL("_precise_mul_result")), VARL("_arg_c"))),
SETL("_normal_result", denorm_to_zere64(VARL("_precise_result"))),
SETL("_rounded_result", FCAST32(FCONVERT, RZ_FLOAT_IEEE754_BIN_32, VARL("_normal_result"), PSW_RM())),
SETL("_result",
ITE(OR(OR(IS_FNAN(VARL("_fa")), IS_FNAN(VARL("_fb"))), IS_FNAN(VARL("_fc"))),
IL_FQNAN(RZ_FLOAT_IEEE754_BIN_32),
ITE(OR(OR(AND(IS_FINF(VARL("_fa")), IS_FZERO(VARL("_fb"))),
AND(IS_FZERO(VARL("_fa")), IS_FINF(VARL("_fb")))),
AND(AND(IS_FINF(VARL("_fa")), IS_FINF(VARL("_fa"))),
IS_FINF(VARL("_fc")))),
IL_FSNAN(RZ_FLOAT_IEEE754_BIN_32),
VARL("_rounded_result")))),
SETG(R(0), F2BV(VARL("_result"))),
set_status);
}

View file

@ -8,9 +8,7 @@
#include <capstone/capstone.h>
#include <tricore/tricore.inc>
RZ_IPI RzAnalysisLiftedILOp tricore_il_op(RzAsmTriCoreContext *ctx, RzAnalysis *a);
RZ_IPI RzAnalysisILConfig *tricore_il_config(RZ_NONNULL RzAnalysis *analysis);
#include "tricore/tricore_il.h"
#define TRICORE_REG_SP TRICORE_REG_A10
@ -241,7 +239,12 @@ static char *tricore_reg_profile(RzAnalysis *_) {
"drx FPU_TRAP_OPC .32 812 0\n"
"drx FPU_TRAP_SRC1 .32 816 0\n"
"drx FPU_TRAP_SRC2 .32 820 0\n"
"drx FPU_TRAP_SRC3 .32 824 0\n";
"drx FPU_TRAP_SRC3 .32 824 0\n"
"drx set_FI .1 900 0\n"
"drx set_FV .1 901 0\n"
"drx set_FZ .1 902 0\n"
"drx set_FU .1 903 0\n"
"drx set_FX .1 904 0\n";
return strdup(p);
}

View file

@ -859,6 +859,10 @@ RZ_IPI void rz_core_il_cons_print(RZ_NONNULL RzCore *core, RZ_NONNULL RZ_BORROW
const char delim = pretty ? '\n' : ' ';
RzStrBuf sb;
RzAnalysisILVM *vm = rz_analysis_il_vm_new(core->analysis, NULL);
RzILValidateGlobalContext *ctx = vm ? rz_il_validate_global_context_new_from_vm(vm->vm)
: NULL;
RzAnalysisOp *op = NULL;
rz_iterator_foreach(iter, op) {
if (!op->il_op) {
@ -868,14 +872,27 @@ RZ_IPI void rz_core_il_cons_print(RZ_NONNULL RzCore *core, RZ_NONNULL RZ_BORROW
rz_strbuf_init(&sb);
rz_il_op_effect_stringify(op->il_op, &sb, pretty);
il_stmt = rz_strbuf_get(&sb);
if (colorize) {
core_colorify_il_statement(core->cons->context, il_stmt, delim, op->addr);
} else {
rz_cons_printf("0x%" PFMT64x "%c%s\n", op->addr, delim, il_stmt);
}
if (ctx) {
RzILTypeEffect t;
char *report;
rz_il_validate_effect(op->il_op, ctx, NULL, &t, &report);
if (report) {
rz_cons_println(report);
free(report);
}
}
rz_strbuf_fini(&sb);
}
rz_analysis_il_vm_free(vm);
rz_il_validate_global_context_free(ctx);
}
// used to speedup strcmp with rz_config_get in loops

View file

@ -20,6 +20,7 @@ RZ_API RZ_OWN RzFloat *rz_il_float_new(RZ_NONNULL RzFloatFormat format, RZ_NONNU
ut32 len = rz_float_get_format_info(format, RZ_FLOAT_INFO_TOTAL_LEN);
if (len != bv->len) {
RZ_LOG_ERROR("The size of the float :%d does not match the size of the bitvector :%d.\n", len, bv->len);
return NULL;
}

View file

@ -1025,6 +1025,9 @@ RZ_API void rz_il_op_effect_stringify(RZ_NONNULL RzILOpEffect *op, RZ_NONNULL Rz
*/
RZ_API char *rz_il_value_stringify(RZ_NONNULL const RzILVal *val) {
rz_return_val_if_fail(val, NULL);
if (val->type == RZ_IL_TYPE_PURE_FLOAT) {
return rz_float_as_string(val->data.f);
}
RzBitVector *bv = rz_il_value_to_bv(val);
if (!bv) {
return NULL;

View file

@ -760,22 +760,27 @@ RZ_API RZ_OWN RzILOpFloat *rz_il_op_new_float(RzFloatFormat format, RZ_NONNULL R
return ret;
}
RZ_API RZ_OWN RzILOpFloat *rz_il_op_new_float_from_rz_float(RZ_NONNULL RZ_OWN RzFloat *fl) {
rz_return_val_if_fail(fl, NULL);
RzILOpFloat *ret = NULL;
RzFloatFormat r = fl->r;
RzILOpBitVector *bv = rz_il_op_new_bitv(fl->s);
if (!bv) {
goto err;
}
fl->s = NULL;
rz_il_op_new_2(Float, RZ_IL_OP_FLOAT, RzILOpArgsFloat, float_, r, bv);
err:
rz_float_free(fl);
return ret;
}
RZ_API RZ_OWN RzILOpFloat *rz_il_op_new_float_from_f32(float f) {
RzFloat *value = rz_float_new_from_f32(f);
if (!value) {
return NULL;
}
RzILOpFloat *ret = RZ_NEW0(RzILOpFloat);
if (!ret) {
rz_float_free(value);
return NULL;
}
ret->code = RZ_IL_OP_FLOAT;
ret->op.float_.bv = rz_il_op_new_bitv(value->s);
ret->op.float_.r = value->r;
free(value);
return ret;
return rz_il_op_new_float_from_rz_float(value);
}
RZ_API RZ_OWN RzILOpFloat *rz_il_op_new_float_from_f64(double f) {
@ -783,17 +788,7 @@ RZ_API RZ_OWN RzILOpFloat *rz_il_op_new_float_from_f64(double f) {
if (!value) {
return NULL;
}
RzILOpFloat *ret = RZ_NEW0(RzILOpFloat);
if (!ret) {
rz_float_free(value);
return NULL;
}
ret->code = RZ_IL_OP_FLOAT;
ret->op.float_.bv = rz_il_op_new_bitv(value->s);
ret->op.float_.r = value->r;
free(value);
return ret;
return rz_il_op_new_float_from_rz_float(value);
}
RZ_API RZ_OWN RzILOpFloat *rz_il_op_new_float_from_f80(long double f) {
@ -801,17 +796,7 @@ RZ_API RZ_OWN RzILOpFloat *rz_il_op_new_float_from_f80(long double f) {
if (!value) {
return NULL;
}
RzILOpFloat *ret = RZ_NEW0(RzILOpFloat);
if (!ret) {
rz_float_free(value);
return NULL;
}
ret->code = RZ_IL_OP_FLOAT;
ret->op.float_.bv = rz_il_op_new_bitv(value->s);
ret->op.float_.r = value->r;
free(value);
return ret;
return rz_il_op_new_float_from_rz_float(value);
}
RZ_API RZ_OWN RzILOpBitVector *rz_il_op_new_fbits(RZ_NONNULL RzILOpFloat *f) {

View file

@ -359,15 +359,10 @@ VALIDATOR_PURE(ite) {
VALIDATOR_DESCEND(args->x, &sx);
RzILSortPure sy;
VALIDATOR_DESCEND(args->y, &sy);
if (!rz_il_sort_pure_eq(sx, sy)) {
char *sxs = rz_il_sort_pure_stringify(sx);
char *sys = rz_il_sort_pure_stringify(sy);
rz_strbuf_appendf(report_builder, "Types of ite branches do not agree: %s vs. %s.\n",
rz_str_get_null(sxs), rz_str_get_null(sys));
free(sxs);
free(sys);
return false;
}
VALIDATOR_ASSERT(rz_il_sort_pure_eq(sx, sy), "Types of ite branches do not agree: %s vs. %s.\n",
rz_il_sort_pure_stringify(sx),
rz_il_sort_pure_stringify(sy));
*sort_out = sx;
return true;
}
@ -611,16 +606,10 @@ VALIDATOR_PURE(forder) {
VALIDATOR_ASSERT(sy.type == RZ_IL_TYPE_PURE_FLOAT, "Right operand of %s op is not a float.\n", rz_il_op_pure_code_stringify(op->code));
// flatten validator assert
if (!(sx.props.f.format == sy.props.f.format)) {
char *ssx = rz_il_sort_pure_stringify(sx);
char *ssy = rz_il_sort_pure_stringify(sy);
rz_strbuf_appendf(report_builder, "Op %s formats of left operand (%s) and right operand (%s) do not agree.\n",
rz_il_op_pure_code_stringify(op->code), ssx, ssy);
free(ssx);
free(ssy);
return false;
}
VALIDATOR_ASSERT(sx.props.f.format == sy.props.f.format, "Op %s formats of left operand (%s) and right operand (%s) do not agree.\n",
rz_il_op_pure_code_stringify(op->code),
rz_il_sort_pure_stringify(sx),
rz_il_sort_pure_stringify(sy));
*sort_out = rz_il_sort_pure_bool();
return true;
@ -652,17 +641,10 @@ VALIDATOR_PURE(float_binop_with_round) {
VALIDATOR_ASSERT(sy.type == RZ_IL_TYPE_PURE_FLOAT, "Right operand of %s op is not a float.\n", rz_il_op_pure_code_stringify(op->code));
// flatten validator assert
if (!(sx.props.f.format == sy.props.f.format)) {
char *ssx = rz_il_sort_pure_stringify(sx);
char *ssy = rz_il_sort_pure_stringify(sy);
rz_strbuf_appendf(report_builder, "Op %s formats of left operand (%s) and right operand (%s) do not agree.\n",
rz_il_op_pure_code_stringify(op->code), ssx, ssy);
free(ssx);
free(ssy);
return false;
}
VALIDATOR_ASSERT(sx.props.f.format == sy.props.f.format, "Op %s formats of left operand (%s) and right operand (%s) do not agree.\n",
rz_il_op_pure_code_stringify(op->code),
rz_il_sort_pure_stringify(sx),
rz_il_sort_pure_stringify(sy));
*sort_out = sx;
return true;
@ -681,22 +663,12 @@ VALIDATOR_PURE(float_terop_with_round) {
VALIDATOR_DESCEND(args->z, &sz);
VALIDATOR_ASSERT(sz.type == RZ_IL_TYPE_PURE_FLOAT, "3rd operand of %s op is not a float.\n", rz_il_op_pure_code_stringify(op->code));
if (!((sx.props.f.format == sy.props.f.format) &&
(sx.props.f.format == sz.props.f.format))) {
char *ssx = rz_il_sort_pure_stringify(sx);
char *ssy = rz_il_sort_pure_stringify(sy);
char *ssz = rz_il_sort_pure_stringify(sz);
rz_strbuf_appendf(report_builder,
"types of operand in op %s do not agree: operand1 (%s) operand2 (%s) operand3 (%s)",
rz_il_op_pure_code_stringify(op->code),
ssx, ssy, ssz);
free(ssx);
free(ssy);
free(ssz);
return false;
}
VALIDATOR_ASSERT((sx.props.f.format == sy.props.f.format) && (sx.props.f.format == sz.props.f.format),
"types of operand in op %s do not agree: operand1 (%s) operand2 (%s) operand3 (%s)",
rz_il_op_pure_code_stringify(op->code),
rz_il_sort_pure_stringify(sx),
rz_il_sort_pure_stringify(sy),
rz_il_sort_pure_stringify(sz));
*sort_out = sx;
return true;

View file

@ -81,6 +81,7 @@
#define FORDER(flx, fly) rz_il_op_new_forder(flx, fly)
#define FROUND(rmode, fl) rz_il_op_new_fround(rmode, fl)
#define FSQRT(rmode, fl) rz_il_op_new_fsqrt(rmode, fl)
#define FRSQRT(rmode, fl) rz_il_op_new_frsqrt(rmode, fl)
#define FADD(rmode, flx, fly) rz_il_op_new_fadd(rmode, flx, fly)
#define FSUB(rmode, flx, fly) rz_il_op_new_fsub(rmode, flx, fly)
#define FMUL(rmode, flx, fly) rz_il_op_new_fmul(rmode, flx, fly)
@ -89,6 +90,9 @@
#define FPOW(rmode, flx, fly) rz_il_op_new_fpow(rmode, flx, fly)
#define FMAD(rmode, flx, fly, flz) rz_il_op_new_fmad(rmode, flx, fly, flz)
#define IL_FQNAN(f) rz_il_op_new_float_from_rz_float(rz_float_new_qnan(f))
#define IL_FSNAN(f) rz_il_op_new_float_from_rz_float(rz_float_new_snan(f))
// TODO: add `feq` as prime operator in fbasic
// https://smtlib.cs.uiowa.edu/theories-FloatingPoint.shtml
@ -99,12 +103,12 @@
#define AND(x, y) rz_il_op_new_bool_and(x, y)
#define OR(x, y) rz_il_op_new_bool_or(x, y)
#define FNEQ(flx, fly) rz_il_op_new_fneq(flx, fly)
#define FEQ(flx, fly) rz_il_op_new_feq(flx, fly)
#define FLT(flx, fly) rz_il_op_new_flt(flx, fly)
#define FLE(flx, fly) rz_il_op_new_fle(flx, fly)
#define FGT(flx, fly) rz_il_op_new_fgt(flx, fly)
#define FGE(flx, fly) rz_il_op_new_fge(flx, fly)
#define FNE(flx, fly) rz_il_op_new_fneq(flx, fly)
#define FEQ(flx, fly) rz_il_op_new_feq(flx, fly)
#define FLT(flx, fly) rz_il_op_new_flt(flx, fly)
#define FLE(flx, fly) rz_il_op_new_fle(flx, fly)
#define FGT(flx, fly) rz_il_op_new_fgt(flx, fly)
#define FGE(flx, fly) rz_il_op_new_fge(flx, fly)
#define UNSIGNED(n, x) rz_il_op_new_unsigned(n, x)
#define SIGNED(n, x) rz_il_op_new_signed(n, x)

View file

@ -55,7 +55,7 @@
#undef FMOD
#undef FPOW
#undef FMAD
#undef FNEQ
#undef FNE
#undef FEQ
#undef FLT
#undef FLE

View file

@ -733,6 +733,7 @@ RZ_API RZ_OWN RzILOpBitVector *rz_il_op_new_append(RZ_NONNULL RzILOpBitVector *h
RZ_API RZ_OWN RzILOpBitVector *rz_il_op_new_load(RzILMemIndex mem, RZ_NONNULL RzILOpBitVector *key);
RZ_API RZ_OWN RzILOpBitVector *rz_il_op_new_loadw(RzILMemIndex mem, RZ_NONNULL RzILOpBitVector *key, ut32 n_bits);
RZ_API RZ_OWN RzILOpFloat *rz_il_op_new_float_from_rz_float(RZ_NONNULL RZ_OWN RzFloat *fl);
RZ_API RZ_OWN RzILOpFloat *rz_il_op_new_float(RzFloatFormat format, RZ_NONNULL RzILOpBitVector *bv);
RZ_API RZ_OWN RzILOpFloat *rz_il_op_new_float_from_f32(float f);
RZ_API RZ_OWN RzILOpFloat *rz_il_op_new_float_from_f64(double f);

View file

@ -276,6 +276,11 @@ drx FPU_TRAP_OPC .32 812 0
drx FPU_TRAP_SRC1 .32 816 0
drx FPU_TRAP_SRC2 .32 820 0
drx FPU_TRAP_SRC3 .32 824 0
drx set_FI .1 900 0
drx set_FV .1 901 0
drx set_FZ .1 902 0
drx set_FU .1 903 0
drx set_FX .1 904 0
EOF
RUN

File diff suppressed because one or more lines are too long

View file

@ -15,3 +15,33 @@ FCX = 0x1
Hello from RzIL!
EOF
RUN
NAME=Testing the decryption in emulateme
FILE=bins/tricore/emulateme-fp.tricore.elf
TIMEOUT=30
CMDS=<<EOF
e io.cache=1
aezi
aezsu 0x80000450 # add.f
ar d2
aezsu 0x80000460 # sub.f
ar d2
aezsu 0x80000470 # mul.f
ar d2
aezsu 0x80000480 # div.f
ar d2
aezsu 0x80000498 # madd.f
ar d2
aezsu 0x800004b0 # msub.f
ar d2
EOF
EXPECT=<<EOF
d2 = 0x47157f3b
d2 = 0x47157f3b
d2 = 0x47157f3b
d2 = 0x47157f3b
d2 = 0x47e03ed8
d2 = 0x489d1884
EOF
RUN