Skip to content

Commit

Permalink
FPU stack regs are 80-bit, not 64-bit
Browse files Browse the repository at this point in the history
  • Loading branch information
DMaroo committed Dec 16, 2023
1 parent 8fdbfd9 commit 34207b8
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 27 deletions.
16 changes: 7 additions & 9 deletions librz/analysis/arch/x86/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1083,11 +1083,11 @@ RzILOpPure *x86_il_fpu_get_rmode() {
* \brief Get the float stored in FPU stack \p reg
*
* \param reg
* \return RzILOpFloat* IEEE754 64 bit float
* \return RzILOpFloat* IEEE754 80 bit float
*/
RzILOpFloat *x86_il_get_st_reg(X86Reg reg) {
rz_return_val_if_fail(x86_il_is_st_reg(reg), NULL);
return BV2F(RZ_FLOAT_IEEE754_BIN_64, VARG(x86_registers[reg]));
return BV2F(RZ_FLOAT_IEEE754_BIN_80, VARG(x86_registers[reg]));
}

#define FLOAT_FORMAT_SWITCH_CASE(n) \
Expand All @@ -1107,7 +1107,7 @@ RzILOpFloat *x86_il_get_st_reg(X86Reg reg) {
* \return RzILOpFloat*
*/
RzILOpFloat *x86_il_resize_floating(RzILOpFloat *val, ut32 width) {
RzFloatFormat format = RZ_FLOAT_IEEE754_BIN_64;
RzFloatFormat format;

switch (width) {
FLOAT_FORMAT_SWITCH_CASE(16);
Expand Down Expand Up @@ -1172,11 +1172,11 @@ RzILOpBitVector *x86_il_int_from_floating(RzILOpFloat *float_val, ut32 width) {
RzILOpEffect *x86_il_set_st_reg(X86Reg reg, RzILOpFloat *val, ut64 val_size) {
rz_return_val_if_fail(x86_il_is_st_reg(reg), NULL);

if (val_size == 64) {
if (val_size == 80) {
return SETG(x86_registers[reg], F2BV(val));
} else {
RzILOpEffect *rmode = INIT_RMODE();
RzILOpFloat *converted_val = x86_il_resize_floating(val, 64);
RzILOpFloat *converted_val = x86_il_resize_floating(val, val_size);

return SEQ2(rmode, SETG(x86_registers[reg], F2BV(converted_val)));
}
Expand Down Expand Up @@ -1211,7 +1211,7 @@ RzILOpEffect *x86_il_set_fpu_stack_top(RzILOpPure *top) {
return x86_il_set_reg_bits(X86_REG_FPSW, new_fpsw, 0);
}

#define ST_MOVE_RIGHT(l, r) x86_il_set_st_reg(X86_REG_ST##r, x86_il_get_st_reg(X86_REG_ST##l), 64)
#define ST_MOVE_RIGHT(l, r) x86_il_set_st_reg(X86_REG_ST##r, x86_il_get_st_reg(X86_REG_ST##l), 80)

RzILOpEffect *x86_il_st_push(RzILOpFloat *val, int val_size) {
/* No need for a modulo here since the bitvector width will truncate any top
Expand All @@ -1234,7 +1234,7 @@ RzILOpEffect *x86_il_st_push(RzILOpFloat *val, int val_size) {
return SEQ3(set_top, st_shift, set_overflow);
}

#define ST_MOVE_LEFT(l, r) x86_il_set_st_reg(X86_REG_ST##l, x86_il_get_st_reg(X86_REG_ST##r), 64)
#define ST_MOVE_LEFT(l, r) x86_il_set_st_reg(X86_REG_ST##l, x86_il_get_st_reg(X86_REG_ST##r), 80)

RzILOpEffect *x86_il_st_pop() {
RzILOpEffect *set_top = x86_il_set_fpu_stack_top(ADD(x86_il_get_fpu_stack_top(), UN(3, 1)));
Expand Down Expand Up @@ -1333,8 +1333,6 @@ RzILOpEffect *x86_il_set_floating_operand_bits(X86Op op, RzILOpFloat *val, ut64

switch (op.type) {
case X86_OP_REG:
/* We assume that the only registers we will be writing to would be the
* FPU stack registers, hence the 64 resize width. */
ret = x86_il_set_st_reg(op.reg, val, val_size);
break;
case X86_OP_MEM: {
Expand Down
36 changes: 18 additions & 18 deletions librz/analysis/arch/x86/il_fp_ops.inc
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ IL_LIFTER(fnclex) {
*/
IL_LIFTER(fabs) {
RzILOpFloat *abs_value = FABS(x86_il_get_st_reg(X86_REG_ST0));
return SEQ2(x86_il_set_st_reg(X86_REG_ST0, abs_value, 64), x86_il_set_fpu_flag(X86_FPU_C1, IL_FALSE));
return SEQ2(x86_il_set_st_reg(X86_REG_ST0, abs_value, 80), x86_il_set_fpu_flag(X86_FPU_C1, IL_FALSE));
}

/**
Expand All @@ -92,7 +92,7 @@ IL_LIFTER(fld) {
* Stores the floating point value stored at the top of the FPU stack in ST(0)
*/
IL_LIFTER(fst) {
return x86_il_set_floating_op(0, x86_il_get_st_reg(X86_REG_ST0), 64);
return x86_il_set_floating_op(0, x86_il_get_st_reg(X86_REG_ST0), 80);
}

/**
Expand All @@ -105,23 +105,23 @@ IL_LIFTER(fstp) {
RzILOpPure *pop_val;
X86_IL_ST_POP(pop_val, pop_eff);

return SEQ2(x86_il_set_floating_op(0, pop_val, 64), pop_eff);
return SEQ2(x86_il_set_floating_op(0, pop_val, 80), pop_eff);
}

/**
* FLD1
* Load +1.0
*/
IL_LIFTER(fld1) {
return x86_il_st_push(F64(1.0), 64);
return x86_il_st_push(F80(1.0), 80);
}

/**
* FLDZ
* Load +0.0
*/
IL_LIFTER(fldz) {
return x86_il_st_push(F64(0.0), 64);
return x86_il_st_push(F80(0.0), 80);
}

/*
Expand All @@ -147,53 +147,53 @@ IL_LIFTER(fldz) {
#define FPU_LN2 0x3ffeb17217f7d1cfULL, 0x79abc9e3b39828efULL

RzILOpFloat *math_const_to_float(uint64_t upper, uint64_t lower) {
RzILOpPure *upper_unshifted = UN(128, upper);
RzILOpPure *upper_shifted = SHIFTL0(upper_unshifted, UN(8, 64));
RzILOpPure *upper_unshifted = UN(80, upper);
RzILOpPure *upper_shifted = SHIFTL0(upper_unshifted, UN(8, 16));

uint64_t stripped_lower = lower & ~(0x3fffffffffffULL);
RzILOpPure *final_bits = LOGOR(upper_shifted, UN(128, stripped_lower));
RzILOpPure *final_bits = LOGOR(upper_shifted, UN(80, (stripped_lower >> (64 - 16))));

return x86_il_resize_floating(BV2F(RZ_FLOAT_IEEE754_BIN_128, final_bits), 64);
return x86_il_resize_floating(BV2F(RZ_FLOAT_IEEE754_BIN_80, final_bits), 80);
}

/**
* FLDL2T
* Load log2(10)
*/
IL_LIFTER(fldl2t) {
return SEQ2(INIT_RMODE(), x86_il_st_push(math_const_to_float(FPU_L2T), 64));
return SEQ2(INIT_RMODE(), x86_il_st_push(math_const_to_float(FPU_L2T), 80));
}

/**
* FLDL2E
* Load log2(e)
*/
IL_LIFTER(fldl2e) {
return SEQ2(INIT_RMODE(), x86_il_st_push(math_const_to_float(FPU_L2E), 64));
return SEQ2(INIT_RMODE(), x86_il_st_push(math_const_to_float(FPU_L2E), 80));
}

/**
* FLDPI
* Load pi
*/
IL_LIFTER(fldpi) {
return SEQ2(INIT_RMODE(), x86_il_st_push(math_const_to_float(FPU_PI), 64));
return SEQ2(INIT_RMODE(), x86_il_st_push(math_const_to_float(FPU_PI), 80));
}

/**
* FLDLG2
* Load log10(2)
*/
IL_LIFTER(fldlg2) {
return SEQ2(INIT_RMODE(), x86_il_st_push(math_const_to_float(FPU_LG2), 64));
return SEQ2(INIT_RMODE(), x86_il_st_push(math_const_to_float(FPU_LG2), 80));
}

/**
* FLDLN2
* Load ln(2)
*/
IL_LIFTER(fldln2) {
return SEQ2(INIT_RMODE(), x86_il_st_push(math_const_to_float(FPU_LN2), 64));
return SEQ2(INIT_RMODE(), x86_il_st_push(math_const_to_float(FPU_LN2), 80));
}

/**
Expand All @@ -215,8 +215,8 @@ IL_LIFTER(fxch) {
but it doesn't matter for now so I'm not bothering with it. */
return SEQ4(
SETL("tmp", x86_il_get_st_reg(X86_REG_ST0)),
x86_il_set_st_reg(X86_REG_ST0, x86_il_get_st_reg(reg), 64),
x86_il_set_st_reg(reg, VARL("tmp"), 64),
x86_il_set_st_reg(X86_REG_ST0, x86_il_get_st_reg(reg), 80),
x86_il_set_st_reg(reg, VARL("tmp"), 80),
x86_il_set_fpu_flag(X86_FPU_C1, IL_FALSE));
}

Expand All @@ -226,9 +226,9 @@ IL_LIFTER(fxch) {
*/
IL_LIFTER(fild) {
RzILOpPure *int_val = x86_il_get_op(0);
RzILOpFloat *float_val = x86_il_floating_from_int(int_val, RZ_FLOAT_IEEE754_BIN_64);
RzILOpFloat *float_val = x86_il_floating_from_int(int_val, RZ_FLOAT_IEEE754_BIN_80);

return SEQ2(INIT_RMODE(), x86_il_st_push(float_val, 64));
return SEQ2(INIT_RMODE(), x86_il_st_push(float_val, 80));
}

/**
Expand Down
18 changes: 18 additions & 0 deletions librz/il/il_opcodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,24 @@ RZ_API RZ_OWN RzILOpFloat *rz_il_op_new_float_from_f64(double f) {
return ret;
}

RZ_API RZ_OWN RzILOpFloat *rz_il_op_new_float_from_f80(long double f) {
RzFloat *value = rz_float_new_from_f80(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;
}

RZ_API RZ_OWN RzILOpBitVector *rz_il_op_new_fbits(RZ_NONNULL RzILOpFloat *f) {
rz_return_val_if_fail(f, NULL);
RzILOpBitVector *ret;
Expand Down
1 change: 1 addition & 0 deletions librz/include/rz_il/rz_il_opbuilder_begin.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#define BV2F(fmt, bv) rz_il_op_new_float(fmt, bv)
#define F32(f32) rz_il_op_new_float_from_f32(f32)
#define F64(f64) rz_il_op_new_float_from_f64(f64)
#define F80(f80) rz_il_op_new_float_from_f80(f80)
#define F2BV(fl) rz_il_op_new_fbits(fl)
#define IS_FINITE(fl) rz_il_op_new_is_finite(fl)
#define IS_FNAN(fl) rz_il_op_new_is_nan(fl)
Expand Down
1 change: 1 addition & 0 deletions librz/include/rz_il/rz_il_opbuilder_end.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#undef BV2F
#undef F32
#undef F64
#undef F80
#undef F2BV
#undef IS_FINITE
#undef IS_FNAN
Expand Down
1 change: 1 addition & 0 deletions librz/include/rz_il/rz_il_opcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,7 @@ RZ_API RZ_OWN RzILOpBitVector *rz_il_op_new_loadw(RzILMemIndex mem, RZ_NONNULL R
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);
RZ_API RZ_OWN RzILOpFloat *rz_il_op_new_float_from_f80(long double f);
RZ_API RZ_OWN RzILOpBitVector *rz_il_op_new_fbits(RZ_NONNULL RzILOpFloat *f);
RZ_API RZ_OWN RzILOpBool *rz_il_op_new_is_finite(RZ_NONNULL RzILOpFloat *f);
RZ_API RZ_OWN RzILOpBool *rz_il_op_new_is_nan(RZ_NONNULL RzILOpFloat *f);
Expand Down

0 comments on commit 34207b8

Please sign in to comment.