Skip to content

Commit

Permalink
Implement FMUL and FIMUL
Browse files Browse the repository at this point in the history
    * Extract the common code into a C macro
  • Loading branch information
DMaroo committed Dec 26, 2023
1 parent 86a9344 commit b560deb
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 46 deletions.
18 changes: 18 additions & 0 deletions librz/analysis/arch/x86/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
3 changes: 2 additions & 1 deletion librz/analysis/arch/x86/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
112 changes: 68 additions & 44 deletions librz/analysis/arch/x86/il_fp_ops.inc
Original file line number Diff line number Diff line change
Expand Up @@ -346,62 +346,86 @@ 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);
}

/**
* FIADD
* 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 <rz_il/rz_il_opbuilder_end.h>
4 changes: 3 additions & 1 deletion librz/analysis/arch/x86/x86_il.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit b560deb

Please sign in to comment.