* Fbasic dev build test * Add fbasic structure and enums * Add fbasic op new * Add fbasic op dup * Add fbasic op free * Add partial theory of float * Add fbasic handlers to pure table default * Add fbasic stringfy * Add temporary float functions * Add rz-float value and evaluation * Add float json dump functions, todo add mode info in il_opdmp_* functions and compelete il_resolve_pure * Complete fbasic il in il_export * Fix detected error in compilation * Add doxygen for il/definition/float * Pack float_round function * Add new version of rounding * Add cast and convert, todo add 'float_get_sign' and 'float_get_no_bias_exp' * Add comments and fix new version rounding * Add util float functions * Implement theory fbasic : cast, convert and round * Remove bv_one warning * Move basic functions into rz_util from definition/float * Add two basic test cmp and extra format test * Add test to fsucc, fpred and fneg * Add round significant test case 1 and fix bug to pass it * Test round significant and bug fixes * Add 6 types test cases to round_and_pack function * Finish round significant and round_pack test with bug fixes and signature changes * Leave fround as unimplement now * Pass all test to cast and convert * Add SPDX header * Add SPDX header * Add round to integral float with test and bug fixes * Add more tests to cast_sint and bug fixes * Fix mem leak in cast_sfloat * Replace the deprecated rounding method, fix bugs and pass tests * Resolve some reviewed issues * Fix most memleak and bug found * Remove deprecated round_bv * Remove unused functions to eliminate warnings * Fix typo in comments * Uncommented implmented operations * Add test cases and bug fixes for fbasic theory in rzil * Fix ret type of new_bitv_from_* from Bool to BitVector * Add new float op from f32 and f64
415 lines
11 KiB
C
415 lines
11 KiB
C
// SPDX-FileCopyrightText: 2023 heersin <teablearcher@gmail.com>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#include <rz_il/rz_il_opcodes.h>
|
|
#include <rz_il/rz_il_vm.h>
|
|
|
|
void *rz_il_handler_float(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsFloat op_f = op->op.float_;
|
|
RzBitVector *bv = rz_il_evaluate_bitv(vm, op_f.bv);
|
|
RzFloat *ret = rz_il_float_new(op_f.r, bv);
|
|
|
|
rz_bv_free(bv);
|
|
|
|
*type = RZ_IL_TYPE_PURE_FLOAT;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_fbits(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsFbits op_fbits = op->op.fbits;
|
|
RzFloat *f = rz_il_evaluate_float(vm, op_fbits.f);
|
|
RzBitVector *ret = rz_bv_dup(f->s);
|
|
|
|
rz_float_free(f);
|
|
|
|
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_is_finite(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsIsFinite is_finite = op->op.is_finite;
|
|
RzFloat *f = rz_il_evaluate_float(vm, is_finite.f);
|
|
RzILBool *ret = rz_il_bool_new(!rz_float_is_inf(f));
|
|
|
|
rz_float_free(f);
|
|
|
|
*type = RZ_IL_TYPE_PURE_BOOL;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_is_nan(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsIsNan is_nan = op->op.is_nan;
|
|
RzFloat *f = rz_il_evaluate_float(vm, is_nan.f);
|
|
RzILBool *ret = rz_il_bool_new(rz_float_is_nan(f));
|
|
|
|
rz_float_free(f);
|
|
|
|
*type = RZ_IL_TYPE_PURE_BOOL;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_is_inf(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsIsInf is_inf = op->op.is_inf;
|
|
RzFloat *f = rz_il_evaluate_float(vm, is_inf.f);
|
|
RzILBool *ret = rz_il_bool_new(rz_float_is_inf(f));
|
|
|
|
rz_float_free(f);
|
|
|
|
*type = RZ_IL_TYPE_PURE_BOOL;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_is_fzero(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsIsFzero is_fzero = op->op.is_fzero;
|
|
RzFloat *f = rz_il_evaluate_float(vm, is_fzero.f);
|
|
RzILBool *ret = rz_il_bool_new(rz_float_is_zero(f));
|
|
|
|
rz_float_free(f);
|
|
|
|
*type = RZ_IL_TYPE_PURE_BOOL;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_is_fneg(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsIsFneg is_fneg = op->op.is_fneg;
|
|
RzFloat *f = rz_il_evaluate_float(vm, is_fneg.f);
|
|
RzILBool *ret = rz_il_bool_new(rz_float_is_negative(f));
|
|
|
|
rz_float_free(f);
|
|
|
|
*type = RZ_IL_TYPE_PURE_BOOL;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_is_fpos(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsIsFpos is_fpos = op->op.is_fpos;
|
|
RzFloat *f = rz_il_evaluate_float(vm, is_fpos.f);
|
|
RzILBool *ret = rz_il_bool_new(!rz_float_is_negative(f));
|
|
|
|
rz_float_free(f);
|
|
|
|
*type = RZ_IL_TYPE_PURE_BOOL;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_fneg(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsFneg fneg = op->op.fneg;
|
|
RzFloat *f = rz_il_evaluate_float(vm, fneg.f);
|
|
RzFloat *ret = rz_float_neg(f);
|
|
|
|
rz_float_free(f);
|
|
|
|
*type = RZ_IL_TYPE_PURE_FLOAT;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_fabs(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsFabs fabs = op->op.fabs;
|
|
RzFloat *f = rz_il_evaluate_float(vm, fabs.f);
|
|
RzFloat *ret = rz_float_abs(f);
|
|
|
|
rz_float_free(f);
|
|
|
|
*type = RZ_IL_TYPE_PURE_FLOAT;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_fcast_int(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsFCastint cast_int = op->op.fcast_int;
|
|
RzFloat *f = rz_il_evaluate_float(vm, cast_int.f);
|
|
ut32 length = cast_int.length;
|
|
RzFloatRMode mode = cast_int.mode;
|
|
RzBitVector *ret = rz_float_cast_int(f, length, mode);
|
|
|
|
rz_float_free(f);
|
|
|
|
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_fcast_sint(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsFCastint cast_sint = op->op.fcast_sint;
|
|
RzFloat *f = rz_il_evaluate_float(vm, cast_sint.f);
|
|
ut32 length = cast_sint.length;
|
|
RzFloatRMode mode = cast_sint.mode;
|
|
RzBitVector *ret = rz_float_cast_sint(f, length, mode);
|
|
|
|
rz_float_free(f);
|
|
|
|
*type = RZ_IL_TYPE_PURE_BITVECTOR;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_fcast_float(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsFCastfloat cast = op->op.fcast_float;
|
|
RzBitVector *bv = rz_il_evaluate_bitv(vm, cast.bv);
|
|
RzFloatFormat format = cast.format;
|
|
RzFloatRMode mode = cast.mode;
|
|
RzFloat *ret = rz_float_cast_float(bv, format, mode);
|
|
|
|
rz_bv_free(bv);
|
|
|
|
*type = RZ_IL_TYPE_PURE_FLOAT;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_fcast_sfloat(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsFCastsfloat cast = op->op.fcast_sfloat;
|
|
RzBitVector *bv = rz_il_evaluate_bitv(vm, cast.bv);
|
|
RzFloatFormat format = cast.format;
|
|
RzFloatRMode mode = cast.mode;
|
|
RzFloat *ret = rz_float_cast_sfloat(bv, format, mode);
|
|
|
|
rz_bv_free(bv);
|
|
|
|
*type = RZ_IL_TYPE_PURE_FLOAT;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_fconvert(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsFconvert convert = op->op.fconvert;
|
|
RzFloat *f = rz_il_evaluate_float(vm, convert.f);
|
|
RzFloatFormat format = convert.format;
|
|
RzFloatRMode mode = convert.mode;
|
|
RzFloat *ret = rz_float_convert(f, format, mode);
|
|
|
|
rz_float_free(f);
|
|
|
|
*type = RZ_IL_TYPE_PURE_FLOAT;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_frequal(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
RzILOpArgsFrequal frequal = op->op.frequal;
|
|
RzILBool *ret = rz_il_bool_new(frequal.x == frequal.y);
|
|
|
|
*type = RZ_IL_TYPE_PURE_BOOL;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_fsucc(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsFsucc fsucc = op->op.fsucc;
|
|
RzFloat *f = rz_il_evaluate_float(vm, fsucc.f);
|
|
RzFloat *ret = rz_float_succ(f);
|
|
|
|
rz_float_free(f);
|
|
|
|
*type = RZ_IL_TYPE_PURE_FLOAT;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_fpred(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsFpred fpred = op->op.fpred;
|
|
RzFloat *f = rz_il_evaluate_float(vm, fpred.f);
|
|
RzFloat *ret = rz_float_pred(f);
|
|
|
|
rz_float_free(f);
|
|
|
|
*type = RZ_IL_TYPE_PURE_FLOAT;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_forder(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsForder forder = op->op.forder;
|
|
RzFloat *x = rz_il_evaluate_float(vm, forder.x);
|
|
RzFloat *y = rz_il_evaluate_float(vm, forder.y);
|
|
RzILBool *order = rz_il_bool_new(rz_float_cmp(x, y) == -1);
|
|
|
|
rz_float_free(x);
|
|
rz_float_free(y);
|
|
|
|
*type = RZ_IL_TYPE_PURE_BOOL;
|
|
return order;
|
|
}
|
|
|
|
void *rz_il_handler_fround(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
|
|
RzILOpArgsFround fround = op->op.fround;
|
|
RzFloat *f = rz_il_evaluate_float(vm, fround.f);
|
|
RzFloatRMode mode = fround.rmode;
|
|
RzFloat *ret = rz_float_round_to_integral(f, mode);
|
|
|
|
rz_float_free(f);
|
|
|
|
*type = RZ_IL_TYPE_PURE_FLOAT;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_fsqrt(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
RzILOpArgsFsqrt sqrt = op->op.fsqrt;
|
|
RzFloat *n = rz_il_evaluate_float(vm, sqrt.f);
|
|
RzFloatRMode mode = sqrt.rmode;
|
|
RzFloat *ret = rz_float_sqrt(n, mode);
|
|
|
|
rz_float_free(n);
|
|
|
|
*type = RZ_IL_TYPE_PURE_FLOAT;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_frsqrt(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
// TODO : float todo unimplemented
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
return NULL;
|
|
}
|
|
|
|
void *rz_il_handler_fadd(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
RzILOpArgsFadd fadd = op->op.fadd;
|
|
RzFloat *x = rz_il_evaluate_float(vm, fadd.x);
|
|
RzFloat *y = rz_il_evaluate_float(vm, fadd.y);
|
|
RzFloatRMode mode = fadd.rmode;
|
|
RzFloat *ret = rz_float_add(x, y, mode);
|
|
|
|
rz_float_free(x);
|
|
rz_float_free(y);
|
|
|
|
*type = RZ_IL_TYPE_PURE_FLOAT;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_fsub(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
RzILOpArgsFsub fsub = op->op.fsub;
|
|
RzFloat *x = rz_il_evaluate_float(vm, fsub.x);
|
|
RzFloat *y = rz_il_evaluate_float(vm, fsub.y);
|
|
RzFloatRMode mode = fsub.rmode;
|
|
RzFloat *ret = rz_float_sub(x, y, mode);
|
|
|
|
rz_float_free(x);
|
|
rz_float_free(y);
|
|
|
|
*type = RZ_IL_TYPE_PURE_FLOAT;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_fdiv(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
RzILOpArgsFdiv fdiv = op->op.fdiv;
|
|
RzFloat *x = rz_il_evaluate_float(vm, fdiv.x);
|
|
RzFloat *y = rz_il_evaluate_float(vm, fdiv.y);
|
|
RzFloatRMode mode = fdiv.rmode;
|
|
RzFloat *ret = rz_float_div(x, y, mode);
|
|
|
|
rz_float_free(x);
|
|
rz_float_free(y);
|
|
|
|
*type = RZ_IL_TYPE_PURE_FLOAT;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_fmul(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
RzILOpArgsFmul fmul = op->op.fmul;
|
|
RzFloat *x = rz_il_evaluate_float(vm, fmul.x);
|
|
RzFloat *y = rz_il_evaluate_float(vm, fmul.y);
|
|
RzFloatRMode mode = fmul.rmode;
|
|
RzFloat *ret = rz_float_mul(x, y, mode);
|
|
|
|
rz_float_free(x);
|
|
rz_float_free(y);
|
|
|
|
*type = RZ_IL_TYPE_PURE_FLOAT;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_fmod(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
RzILOpArgsFmod fmod = op->op.fmod;
|
|
RzFloat *x = rz_il_evaluate_float(vm, fmod.x);
|
|
RzFloat *y = rz_il_evaluate_float(vm, fmod.y);
|
|
RzFloatRMode mode = fmod.rmode;
|
|
RzFloat *ret = rz_float_mod(x, y, mode);
|
|
|
|
rz_float_free(x);
|
|
rz_float_free(y);
|
|
|
|
*type = RZ_IL_TYPE_PURE_FLOAT;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_fhypot(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
// TODO : float todo unimplemented
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
return NULL;
|
|
}
|
|
|
|
void *rz_il_handler_fpow(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
// TODO : float todo unimplemented
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
return NULL;
|
|
}
|
|
|
|
void *rz_il_handler_fmad(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
RzILOpArgsFmad fmad = op->op.fmad;
|
|
RzFloat *x = rz_il_evaluate_float(vm, fmad.x);
|
|
RzFloat *y = rz_il_evaluate_float(vm, fmad.y);
|
|
RzFloat *z = rz_il_evaluate_float(vm, fmad.z);
|
|
RzFloatRMode mode = fmad.rmode;
|
|
RzFloat *ret = rz_float_fma(x, y, z, mode);
|
|
|
|
rz_float_free(x);
|
|
rz_float_free(y);
|
|
rz_float_free(z);
|
|
|
|
*type = RZ_IL_TYPE_PURE_FLOAT;
|
|
return ret;
|
|
}
|
|
|
|
void *rz_il_handler_frootn(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
// TODO : float todo unimplemented
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
return NULL;
|
|
}
|
|
|
|
void *rz_il_handler_fpown(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
// TODO : float todo unimplemented
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
return NULL;
|
|
}
|
|
|
|
void *rz_il_handler_fcompound(RzILVM *vm, RzILOpPure *op, RzILTypePure *type) {
|
|
// TODO : float todo unimplemented
|
|
rz_return_val_if_fail(vm && op && type, NULL);
|
|
return NULL;
|
|
}
|