diff --git a/librz/analysis/arch/x86/common.c b/librz/analysis/arch/x86/common.c index 6314bacf5b9..09b86d90d99 100644 --- a/librz/analysis/arch/x86/common.c +++ b/librz/analysis/arch/x86/common.c @@ -1149,6 +1149,24 @@ RzILOpFloat *x86_il_fadd_with_rmode(RzILOpFloat *x, RzILOpFloat *y) { return ret; } +/** + * \brief Multiply \p x and \p y with the correct rounding mode as determined + * from the FPU control word + * + * \param x Desirable that it is a small expression since it will be duped + * \param y Desirable that it is a small expression since it will be duped + * \return RzILOpFloat* product + */ +RzILOpFloat *x86_il_fmul_with_rmode(RzILOpFloat *x, RzILOpFloat *y) { + use_rmode = true; + RzILOpFloat *ret = EXEC_WITH_RMODE(FMUL, DUP(x), DUP(y)); + + rz_il_op_pure_free(x); + rz_il_op_pure_free(y); + + return ret; +} + RzILOpFloat *sint2f_floating_helper(RzFloatRMode rmode, RzFloatFormat format, RzILOpBitVector *val) { return SINT2F(format, rmode, val); } diff --git a/librz/analysis/arch/x86/common.h b/librz/analysis/arch/x86/common.h index 04fc2cc347c..f61dfb47dc7 100644 --- a/librz/analysis/arch/x86/common.h +++ b/librz/analysis/arch/x86/common.h @@ -154,9 +154,10 @@ RzILOpEffect *init_rmode(); RzILOpFloat *x86_il_resize_floating(RzILOpFloat *val, RzFloatFormat format); RzILOpFloat *x86_il_fadd_with_rmode(RzILOpFloat *x, RzILOpFloat *y); +RzILOpBitVector *x86_il_int_from_floating(RzILOpFloat *float_val, ut32 width); RzILOpFloat *x86_il_floating_from_int(RzILOpBitVector *int_val, RzFloatFormat format); -RzILOpBitVector *x86_il_int_from_floating(RzILOpFloat *float_val, ut32 width); +RzILOpFloat *x86_il_fmul_with_rmode(RzILOpFloat *x, RzILOpFloat *y); RzILOpPure *x86_il_get_floating_operand_bits(X86Op op, int analysis_bits, ut64 pc); diff --git a/librz/analysis/arch/x86/il_fp_ops.inc b/librz/analysis/arch/x86/il_fp_ops.inc index 0e11cfa487b..8bfa293ac9c 100644 --- a/librz/analysis/arch/x86/il_fp_ops.inc +++ b/librz/analysis/arch/x86/il_fp_ops.inc @@ -346,52 +346,62 @@ IL_LIFTER(fabs) { return SEQ2(x86_il_set_st_reg(X86_REG_ST0, abs_value, RZ_FLOAT_IEEE754_BIN_80), x86_il_set_fpu_flag(X86_FPU_C1, IL_FALSE)); } +#define FLOATING_ARTITHMETIC_IL(op) do { \ + RzILOpFloat *src; \ + X86Reg dest_reg; \ + \ + /* Capstone does not differentiate between FADD and FADDP, so we need to \ + * manually check whether we need to pop the stack the the end not. */ \ + bool pop = false; \ + \ + /* TODO: Check whether all the enumerated cases here are correct, through \ + * code coverage. */ \ + switch (ins->structure->op_count) { \ + case 0: \ + /* FADDP with no arguments */ \ + pop = true; \ + dest_reg = X86_REG_ST1; \ + src = x86_il_get_st_reg(X86_REG_ST0); \ + break; \ + case 1: \ + /* Need to convert a 32-bit or 64-bit memory operand */ \ + dest_reg = X86_REG_ST0; \ + src = x86_il_resize_floating(x86_il_get_floating_op(0), RZ_FLOAT_IEEE754_BIN_80); \ + break; \ + case 2: \ + /* ST(i) operand, so no need for resizing */ \ + dest_reg = ins->structure->operands[0].reg; \ + src = x86_il_get_floating_op(0); \ + \ + /* Check if this is FADDP */ \ + if (ins->structure->opcode[0] == 0xde) { \ + pop = true; \ + } \ + break; \ + default: \ + rz_warn_if_reached(); \ + return NULL; \ + } \ + \ + RzILOpFloat *sum = x86_il_##op##_with_rmode(src, x86_il_get_st_reg(dest_reg)); \ + RzILOpEffect *store = x86_il_set_st_reg(dest_reg, sum, RZ_FLOAT_IEEE754_BIN_80); \ + RzILOpEffect *store_and_maybe_pop = (pop ? SEQ2(store, x86_il_st_pop()) : store); \ + \ + return store_and_maybe_pop; \ +} while (0) + +#define FLOATING_INT_ARTITHMETIC_IL(op) do { \ + RzILOpPure *float_val = x86_il_floating_from_int(x86_il_get_op(0), RZ_FLOAT_IEEE754_BIN_80); \ + RzILOpPure *sum = x86_il_fadd_with_rmode(x86_il_get_st_reg(X86_REG_ST0), float_val); \ + return x86_il_set_st_reg(X86_REG_ST0, sum, RZ_FLOAT_IEEE754_BIN_80); \ +} while(0) + /** * FADD * Add floating point values */ IL_LIFTER(fadd) { - RzILOpFloat *src; - X86Reg dest_reg; - - /* Capstone does not differentiate between FADD and FADDP, so we need to - * manually check whether we need to pop the stack the the end not. */ - bool pop = false; - - /* TODO: Check whether all the enumerated cases here are correct, through - * code coverage. */ - switch (ins->structure->op_count) { - case 0: - /* FADDP with no arguments */ - pop = true; - dest_reg = X86_REG_ST1; - src = x86_il_get_st_reg(X86_REG_ST0); - break; - case 1: - /* Need to convert a 32-bit or 64-bit memory operand */ - dest_reg = X86_REG_ST0; - src = x86_il_resize_floating(x86_il_get_floating_op(0), RZ_FLOAT_IEEE754_BIN_80); - break; - case 2: - /* ST(i) operand, so no need for resizing */ - dest_reg = ins->structure->operands[0].reg; - src = x86_il_get_floating_op(0); - - /* Check if this is FADDP */ - if (ins->structure->opcode[0] == 0xde) { - pop = true; - } - break; - default: - rz_warn_if_reached(); - return NULL; - } - - RzILOpFloat *sum = x86_il_fadd_with_rmode(src, x86_il_get_st_reg(dest_reg)); - RzILOpEffect *store = x86_il_set_st_reg(dest_reg, sum, RZ_FLOAT_IEEE754_BIN_80); - RzILOpEffect *store_and_maybe_pop = (pop ? SEQ2(store, x86_il_st_pop()) : store); - - return store_and_maybe_pop; + FLOATING_ARTITHMETIC_IL(fadd); } /** @@ -399,9 +409,23 @@ IL_LIFTER(fadd) { * Add an integer to ST(0) */ IL_LIFTER(fiadd) { - RzILOpPure *float_val = x86_il_floating_from_int(x86_il_get_op(0), RZ_FLOAT_IEEE754_BIN_80); - RzILOpPure *sum = x86_il_fadd_with_rmode(x86_il_get_st_reg(X86_REG_ST0), float_val); - return x86_il_set_st_reg(X86_REG_ST0, sum, RZ_FLOAT_IEEE754_BIN_80); + FLOATING_INT_ARTITHMETIC_IL(fadd); +} + +/** + * FMUL + * Multiply floating point values + */ +IL_LIFTER(fmul) { + FLOATING_ARTITHMETIC_IL(fmul); +} + +/** + * FIMUL + * Multiply an integer to ST(0) + */ +IL_LIFTER(fimul) { + FLOATING_INT_ARTITHMETIC_IL(fmul); } #include diff --git a/librz/analysis/arch/x86/x86_il.c b/librz/analysis/arch/x86/x86_il.c index 715f5274281..cfad3e290e1 100644 --- a/librz/analysis/arch/x86/x86_il.c +++ b/librz/analysis/arch/x86/x86_il.c @@ -276,7 +276,9 @@ x86_il_ins x86_ins[X86_INS_ENDING] = { [X86_INS_FBSTP] = x86_il_fbstp, [X86_INS_FABS] = x86_il_fabs, [X86_INS_FADD] = x86_il_fadd, - [X86_INS_FIADD] = x86_il_fiadd + [X86_INS_FIADD] = x86_il_fiadd, + [X86_INS_FMUL] = x86_il_fmul, + [X86_INS_FIMUL] = x86_il_fimul }; void label_int(RzILVM *vm, RzILOpEffect *op);