diff --git a/src/vm/fp_functions.cpp b/src/vm/fp_functions.cpp index ac48073..076ae5d 100644 --- a/src/vm/fp_functions.cpp +++ b/src/vm/fp_functions.cpp @@ -46,585 +46,6 @@ extern "C" { #include using this_t = uint8_t*; -extern "C" { - -uint32_t fget_flags() { return softfloat_exceptionFlags & 0x1f; } -uint16_t fadd_h(uint16_t v1, uint16_t v2, uint8_t mode) { - float16_t v1f{v1}, v2f{v2}; - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float16_t r = f16_add(v1f, v2f); - return r.v; -} - -uint16_t fsub_h(uint16_t v1, uint16_t v2, uint8_t mode) { - float16_t v1f{v1}, v2f{v2}; - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float16_t r = f16_sub(v1f, v2f); - return r.v; -} - -uint16_t fmul_h(uint16_t v1, uint16_t v2, uint8_t mode) { - float16_t v1f{v1}, v2f{v2}; - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float16_t r = f16_mul(v1f, v2f); - return r.v; -} - -uint16_t fdiv_h(uint16_t v1, uint16_t v2, uint8_t mode) { - float16_t v1f{v1}, v2f{v2}; - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float16_t r = f16_div(v1f, v2f); - return r.v; -} - -uint16_t fsqrt_h(uint16_t v1, uint8_t mode) { - float16_t v1f{v1}; - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float16_t r = f16_sqrt(v1f); - return r.v; -} - -uint16_t fcmp_h(uint16_t v1, uint16_t v2, uint16_t op) { - float16_t v1f{v1}, v2f{v2}; - softfloat_exceptionFlags = 0; - bool nan = v1 == defaultNaNF16UI || v2 & defaultNaNF16UI; - bool snan = softfloat_isSigNaNF16UI(v1) || softfloat_isSigNaNF16UI(v2); - switch(op) { - case 0: - if(nan | snan) { - if(snan) - softfloat_raiseFlags(softfloat_flag_invalid); - return 0; - } else - return f16_eq(v1f, v2f) ? 1 : 0; - case 1: - if(nan | snan) { - softfloat_raiseFlags(softfloat_flag_invalid); - return 0; - } else - return f16_le(v1f, v2f) ? 1 : 0; - case 2: - if(nan | snan) { - softfloat_raiseFlags(softfloat_flag_invalid); - return 0; - } else - return f16_lt(v1f, v2f) ? 1 : 0; - default: - break; - } - return -1; -} - -uint16_t fcvt_h(uint16_t v1, uint16_t op, uint8_t mode) { - float16_t v1f{v1}; - softfloat_exceptionFlags = 0; - float16_t r; - switch(op) { - case 0: { // FCVT__W__H - uint_fast16_t res = f16_to_i32(v1f, mode, true); - return (uint16_t)res; - } - case 1: { // FCVT__WU__H - uint_fast16_t res = f16_to_ui32(v1f, mode, true); - return (uint16_t)res; - } - case 2: // FCVT__H__W - r = i32_to_f16((int16_t)v1); - return r.v; - case 3: // FCVT__H__WU - r = ui32_to_f16(v1); - return r.v; - } - return 0; -} - -uint16_t fmadd_h(uint16_t v1, uint16_t v2, uint16_t v3, uint16_t op, uint8_t mode) { - uint16_t F16_SIGN = 1UL << 15; - switch(op) { - case 0: // FMADD_S - break; - case 1: // FMSUB_S - v3 ^= F16_SIGN; - break; - case 2: // FNMADD_S - v1 ^= F16_SIGN; - v3 ^= F16_SIGN; - break; - case 3: // FNMSUB_S - v1 ^= F16_SIGN; - break; - } - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float16_t res = softfloat_mulAddF16(v1, v2, v3, 0); - return res.v; -} - -uint16_t fsel_h(uint16_t v1, uint16_t v2, uint16_t op) { - softfloat_exceptionFlags = 0; - bool v1_nan = (v1 & defaultNaNF16UI) == defaultNaNF16UI; - bool v2_nan = (v2 & defaultNaNF16UI) == defaultNaNF16UI; - bool v1_snan = softfloat_isSigNaNF16UI(v1); - bool v2_snan = softfloat_isSigNaNF16UI(v2); - if(v1_snan || v2_snan) - softfloat_raiseFlags(softfloat_flag_invalid); - if(v1_nan || v1_snan) - return (v2_nan || v2_snan) ? defaultNaNF16UI : v2; - else if(v2_nan || v2_snan) - return v1; - else { - if((v1 & 0x7fff) == 0 && (v2 & 0x7fff) == 0) { - return op == 0 ? ((v1 & 0x8000) ? v1 : v2) : ((v1 & 0x8000) ? v2 : v1); - } else { - float16_t v1f{v1}, v2f{v2}; - return op == 0 ? (f16_lt(v1f, v2f) ? v1 : v2) : (f16_lt(v1f, v2f) ? v2 : v1); - } - } -} - -uint16_t fclass_h(uint16_t v1) { - - float16_t a{v1}; - union ui16_f16 uA; - uint_fast16_t uiA; - - uA.f = a; - uiA = uA.ui; - - bool infOrNaN = expF16UI(uiA) == 0x1F; - bool subnormalOrZero = expF16UI(uiA) == 0; - bool sign = signF16UI(uiA); - bool fracZero = fracF16UI(uiA) == 0; - bool isNaN = isNaNF16UI(uiA); - bool isSNaN = softfloat_isSigNaNF16UI(uiA); - - return (sign && infOrNaN && fracZero) << 0 | (sign && !infOrNaN && !subnormalOrZero) << 1 | - (sign && subnormalOrZero && !fracZero) << 2 | (sign && subnormalOrZero && fracZero) << 3 | (!sign && infOrNaN && fracZero) << 7 | - (!sign && !infOrNaN && !subnormalOrZero) << 6 | (!sign && subnormalOrZero && !fracZero) << 5 | - (!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9; -} -uint16_t unbox_h(uint8_t FLEN, uint64_t v) { - uint64_t mask = 0; - switch(FLEN) { - case 32: { - mask = std::numeric_limits::max() & ~((uint64_t)std::numeric_limits::max()); - break; - } - case 64: { - mask = std::numeric_limits::max() & ~((uint64_t)std::numeric_limits::max()); - break; - } - default: - break; - } - if((v & mask) != mask) - return 0x7e00; - else - return v & std::numeric_limits::max(); -} - -uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode) { - float32_t v1f{v1}, v2f{v2}; - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float32_t r = f32_add(v1f, v2f); - return r.v; -} - -uint32_t fsub_s(uint32_t v1, uint32_t v2, uint8_t mode) { - float32_t v1f{v1}, v2f{v2}; - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float32_t r = f32_sub(v1f, v2f); - return r.v; -} - -uint32_t fmul_s(uint32_t v1, uint32_t v2, uint8_t mode) { - float32_t v1f{v1}, v2f{v2}; - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float32_t r = f32_mul(v1f, v2f); - return r.v; -} - -uint32_t fdiv_s(uint32_t v1, uint32_t v2, uint8_t mode) { - float32_t v1f{v1}, v2f{v2}; - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float32_t r = f32_div(v1f, v2f); - return r.v; -} - -uint32_t fsqrt_s(uint32_t v1, uint8_t mode) { - float32_t v1f{v1}; - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float32_t r = f32_sqrt(v1f); - return r.v; -} - -uint32_t fcmp_s(uint32_t v1, uint32_t v2, uint32_t op) { - float32_t v1f{v1}, v2f{v2}; - softfloat_exceptionFlags = 0; - bool nan = v1 == defaultNaNF32UI || v2 == defaultNaNF32UI; - bool snan = softfloat_isSigNaNF32UI(v1) || softfloat_isSigNaNF32UI(v2); - switch(op) { - case 0: - if(nan | snan) { - if(snan) - softfloat_raiseFlags(softfloat_flag_invalid); - return 0; - } else - return f32_eq(v1f, v2f) ? 1 : 0; - case 1: - if(nan | snan) { - softfloat_raiseFlags(softfloat_flag_invalid); - return 0; - } else - return f32_le(v1f, v2f) ? 1 : 0; - case 2: - if(nan | snan) { - softfloat_raiseFlags(softfloat_flag_invalid); - return 0; - } else - return f32_lt(v1f, v2f) ? 1 : 0; - default: - break; - } - return -1; -} - -uint32_t fcvt_s(uint32_t v1, uint32_t op, uint8_t mode) { - float32_t v1f{v1}; - softfloat_exceptionFlags = 0; - float32_t r; - switch(op) { - case 0: { // FCVT__W__S - uint_fast32_t res = f32_to_i32(v1f, mode, true); - return (uint32_t)res; - } - case 1: { // FCVT__WU__S - uint_fast32_t res = f32_to_ui32(v1f, mode, true); - return (uint32_t)res; - } - case 2: // FCVT__S__W - r = i32_to_f32((int32_t)v1); - return r.v; - case 3: // FCVT__S__WU - r = ui32_to_f32(v1); - return r.v; - } - return 0; -} - -uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mode) { - uint32_t F32_SIGN = 1UL << 31; - switch(op) { - case 0: // FMADD_S - break; - case 1: // FMSUB_S - v3 ^= F32_SIGN; - break; - case 2: // FNMADD_S - v1 ^= F32_SIGN; - v3 ^= F32_SIGN; - break; - case 3: // FNMSUB_S - v1 ^= F32_SIGN; - break; - } - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float32_t res = softfloat_mulAddF32(v1, v2, v3, 0); - return res.v; -} - -uint32_t fsel_s(uint32_t v1, uint32_t v2, uint32_t op) { - softfloat_exceptionFlags = 0; - bool v1_nan = (v1 & defaultNaNF32UI) == defaultNaNF32UI; - bool v2_nan = (v2 & defaultNaNF32UI) == defaultNaNF32UI; - bool v1_snan = softfloat_isSigNaNF32UI(v1); - bool v2_snan = softfloat_isSigNaNF32UI(v2); - if(v1_snan || v2_snan) - softfloat_raiseFlags(softfloat_flag_invalid); - if(v1_nan || v1_snan) - return (v2_nan || v2_snan) ? defaultNaNF32UI : v2; - else if(v2_nan || v2_snan) - return v1; - else { - if((v1 & 0x7fffffff) == 0 && (v2 & 0x7fffffff) == 0) { - return op == 0 ? ((v1 & 0x80000000) ? v1 : v2) : ((v1 & 0x80000000) ? v2 : v1); - } else { - float32_t v1f{v1}, v2f{v2}; - return op == 0 ? (f32_lt(v1f, v2f) ? v1 : v2) : (f32_lt(v1f, v2f) ? v2 : v1); - } - } -} - -uint32_t fclass_s(uint32_t v1) { - - float32_t a{v1}; - union ui32_f32 uA; - uint_fast32_t uiA; - - uA.f = a; - uiA = uA.ui; - - bool infOrNaN = expF32UI(uiA) == 0xFF; - bool subnormalOrZero = expF32UI(uiA) == 0; - bool sign = signF32UI(uiA); - bool fracZero = fracF32UI(uiA) == 0; - bool isNaN = isNaNF32UI(uiA); - bool isSNaN = softfloat_isSigNaNF32UI(uiA); - - return (sign && infOrNaN && fracZero) << 0 | (sign && !infOrNaN && !subnormalOrZero) << 1 | - (sign && subnormalOrZero && !fracZero) << 2 | (sign && subnormalOrZero && fracZero) << 3 | (!sign && infOrNaN && fracZero) << 7 | - (!sign && !infOrNaN && !subnormalOrZero) << 6 | (!sign && subnormalOrZero && !fracZero) << 5 | - (!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9; -} - -uint32_t fconv_d2f(uint64_t v1, uint8_t mode) { - if(softfloat_isSigNaNF64UI(v1)) { - softfloat_raiseFlags(softfloat_flag_invalid); - return defaultNaNF32UI; - } else { - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float32_t res = f64_to_f32(float64_t{v1}); - return res.v; - } -} - -uint64_t fconv_f2d(uint32_t v1, uint8_t mode) { - bool infOrNaN = expF32UI(v1) == 0xFF; - bool subnormalOrZero = expF32UI(v1) == 0; - if(infOrNaN || subnormalOrZero) { - return defaultNaNF64UI; - } else { - float64_t res = f32_to_f64(float32_t{v1}); - return res.v; - } -} - -uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode) { - bool nan = v1 == defaultNaNF32UI; - bool snan = softfloat_isSigNaNF32UI(v1); - float64_t v1f{v1}, v2f{v2}; - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float64_t r = f64_add(v1f, v2f); - return r.v; -} - -uint64_t fsub_d(uint64_t v1, uint64_t v2, uint8_t mode) { - float64_t v1f{v1}, v2f{v2}; - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float64_t r = f64_sub(v1f, v2f); - return r.v; -} - -uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode) { - float64_t v1f{v1}, v2f{v2}; - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float64_t r = f64_mul(v1f, v2f); - return r.v; -} - -uint64_t fdiv_d(uint64_t v1, uint64_t v2, uint8_t mode) { - float64_t v1f{v1}, v2f{v2}; - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float64_t r = f64_div(v1f, v2f); - return r.v; -} - -uint64_t fsqrt_d(uint64_t v1, uint8_t mode) { - float64_t v1f{v1}; - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float64_t r = f64_sqrt(v1f); - return r.v; -} - -uint64_t fcmp_d(uint64_t v1, uint64_t v2, uint32_t op) { - float64_t v1f{v1}, v2f{v2}; - softfloat_exceptionFlags = 0; - bool nan = v1 == defaultNaNF64UI || v2 == defaultNaNF64UI; - bool snan = softfloat_isSigNaNF64UI(v1) || softfloat_isSigNaNF64UI(v2); - switch(op) { - case 0: - if(nan | snan) { - if(snan) - softfloat_raiseFlags(softfloat_flag_invalid); - return 0; - } else - return f64_eq(v1f, v2f) ? 1 : 0; - case 1: - if(nan | snan) { - softfloat_raiseFlags(softfloat_flag_invalid); - return 0; - } else - return f64_le(v1f, v2f) ? 1 : 0; - case 2: - if(nan | snan) { - softfloat_raiseFlags(softfloat_flag_invalid); - return 0; - } else - return f64_lt(v1f, v2f) ? 1 : 0; - default: - break; - } - return -1; -} - -uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode) { - - float64_t v1f{v1}; - softfloat_exceptionFlags = 0; - float64_t r; - switch(op) { - case 0: { // l from d - int64_t res = f64_to_i64(v1f, mode, true); - return (uint64_t)res; - } - case 1: { // lu from d - uint64_t res = f64_to_ui64(v1f, mode, true); - return res; - } - case 2: // d from l - r = i64_to_f64(v1); - return r.v; - case 3: // d from lu - r = ui64_to_f64(v1); - return r.v; - } - return 0; -} - -uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode) { - uint64_t F64_SIGN = 1ULL << 63; - switch(op) { - case 0: // FMADD_D - break; - case 1: // FMSUB_D - v3 ^= F64_SIGN; - break; - case 2: // FNMADD_D - v1 ^= F64_SIGN; - v3 ^= F64_SIGN; - break; - case 3: // FNMSUB_D - v1 ^= F64_SIGN; - break; - } - softfloat_roundingMode = mode; - softfloat_exceptionFlags = 0; - float64_t res = softfloat_mulAddF64(v1, v2, v3, 0); - return res.v; -} - -uint64_t fsel_d(uint64_t v1, uint64_t v2, uint32_t op) { - softfloat_exceptionFlags = 0; - bool v1_nan = (v1 & defaultNaNF64UI) == defaultNaNF64UI; - bool v2_nan = (v2 & defaultNaNF64UI) == defaultNaNF64UI; - bool v1_snan = softfloat_isSigNaNF64UI(v1); - bool v2_snan = softfloat_isSigNaNF64UI(v2); - if(v1_snan || v2_snan) - softfloat_raiseFlags(softfloat_flag_invalid); - if(v1_nan || v1_snan) - return (v2_nan || v2_snan) ? defaultNaNF64UI : v2; - else if(v2_nan || v2_snan) - return v1; - else { - if((v1 & std::numeric_limits::max()) == 0 && (v2 & std::numeric_limits::max()) == 0) { - return op == 0 ? ((v1 & std::numeric_limits::min()) ? v1 : v2) - : ((v1 & std::numeric_limits::min()) ? v2 : v1); - } else { - float64_t v1f{v1}, v2f{v2}; - return op == 0 ? (f64_lt(v1f, v2f) ? v1 : v2) : (f64_lt(v1f, v2f) ? v2 : v1); - } - } -} - -uint64_t fclass_d(uint64_t v1) { - - float64_t a{v1}; - union ui64_f64 uA; - uint_fast64_t uiA; - - uA.f = a; - uiA = uA.ui; - - bool infOrNaN = expF64UI(uiA) == 0x7FF; - bool subnormalOrZero = expF64UI(uiA) == 0; - bool sign = signF64UI(uiA); - bool fracZero = fracF64UI(uiA) == 0; - bool isNaN = isNaNF64UI(uiA); - bool isSNaN = softfloat_isSigNaNF64UI(uiA); - - return (sign && infOrNaN && fracZero) << 0 | (sign && !infOrNaN && !subnormalOrZero) << 1 | - (sign && subnormalOrZero && !fracZero) << 2 | (sign && subnormalOrZero && fracZero) << 3 | (!sign && infOrNaN && fracZero) << 7 | - (!sign && !infOrNaN && !subnormalOrZero) << 6 | (!sign && subnormalOrZero && !fracZero) << 5 | - (!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9; -} - -uint64_t fcvt_32_64(uint32_t v1, uint32_t op, uint8_t mode) { - float32_t v1f{v1}; - softfloat_exceptionFlags = 0; - float64_t r; - switch(op) { - case 0: // l->s, fp to int32 - return f32_to_i64(v1f, mode, true); - case 1: // wu->s - return f32_to_ui64(v1f, mode, true); - case 2: // s->w - r = i32_to_f64(v1); - return r.v; - case 3: // s->wu - r = ui32_to_f64(v1); - return r.v; - } - return 0; -} - -uint32_t fcvt_64_32(uint64_t v1, uint32_t op, uint8_t mode) { - softfloat_exceptionFlags = 0; - float32_t r; - switch(op) { - case 0: { // wu->s - int32_t r = f64_to_i32(float64_t{v1}, mode, true); - return r; - } - case 1: { // wu->s - uint32_t r = f64_to_ui32(float64_t{v1}, mode, true); - return r; - } - case 2: // l->s, fp to int32 - r = i64_to_f32(v1); - return r.v; - case 3: // wu->s - r = ui64_to_f32(v1); - return r.v; - } - return 0; -} - -uint32_t unbox_s(uint64_t v) { - constexpr uint64_t mask = std::numeric_limits::max() & ~((uint64_t)std::numeric_limits::max()); - if((v & mask) != mask) - return 0x7fc00000; - else - return v & std::numeric_limits::max(); -} -} - template T constexpr defaultNaN(); template <> uint16_t constexpr defaultNaN() { return defaultNaNF16UI; } template <> uint32_t constexpr defaultNaN() { return defaultNaNF32UI; } @@ -719,47 +140,6 @@ uint64_t constexpr frsqrt7_general(const unsigned s, const unsigned e, const uin // The output sign equals the input sign. return (sign << (s + e)) | (out_exp << s) | out_sig; } - -uint16_t frsqrt7_h(uint16_t v) { - bool subnormal = false; - uint16_t ret_val = 0; - if(rsqrt_check(fclass_h(v), subnormal, ret_val)) { - return ret_val; - } - uint16_t sig = fracF64UI(v); - int16_t exp = expF64UI(v); - uint16_t sign = signF64UI(v); - unsigned constexpr e = 5; - unsigned constexpr s = 10; - return frsqrt7_general(s, e, sign, exp, sig, subnormal); -} -uint32_t frsqrt7_s(uint32_t v) { - bool subnormal = false; - uint32_t ret_val = 0; - if(rsqrt_check(fclass_s(v), subnormal, ret_val)) { - return ret_val; - } - uint32_t sig = fracF32UI(v); - int exp = expF32UI(v); - uint32_t sign = signF32UI(v); - unsigned constexpr e = 8; - unsigned constexpr s = 23; - return frsqrt7_general(s, e, sign, exp, sig, subnormal); -} -uint64_t frsqrt7_d(uint64_t v) { - bool subnormal = false; - uint64_t ret_val = 0; - if(rsqrt_check(fclass_d(v), subnormal, ret_val)) { - return ret_val; - } - uint64_t sig = fracF64UI(v); - int exp = expF64UI(v); - uint64_t sign = signF64UI(v); - unsigned constexpr e = 11; - unsigned constexpr s = 52; - return frsqrt7_general(s, e, sign, exp, sig, subnormal); -} - template bool recip_check(T fclass_val, bool& subnormal, uint64_t& ret_val) { softfloat_exceptionFlags = 0; switch(fclass_val) { @@ -841,6 +221,161 @@ bool frec_general(uint64_t& res, const unsigned s, const unsigned e, const uint6 res = (sign << (s + e)) | (out_exp << s) | out_sig; return false; } + +extern "C" { + +uint32_t fget_flags() { return softfloat_exceptionFlags & 0x1f; } +uint16_t fadd_h(uint16_t v1, uint16_t v2, uint8_t mode) { + float16_t v1f{v1}, v2f{v2}; + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float16_t r = f16_add(v1f, v2f); + return r.v; +} + +uint16_t fsub_h(uint16_t v1, uint16_t v2, uint8_t mode) { + float16_t v1f{v1}, v2f{v2}; + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float16_t r = f16_sub(v1f, v2f); + return r.v; +} + +uint16_t fmul_h(uint16_t v1, uint16_t v2, uint8_t mode) { + float16_t v1f{v1}, v2f{v2}; + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float16_t r = f16_mul(v1f, v2f); + return r.v; +} + +uint16_t fdiv_h(uint16_t v1, uint16_t v2, uint8_t mode) { + float16_t v1f{v1}, v2f{v2}; + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float16_t r = f16_div(v1f, v2f); + return r.v; +} + +uint16_t fsqrt_h(uint16_t v1, uint8_t mode) { + float16_t v1f{v1}; + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float16_t r = f16_sqrt(v1f); + return r.v; +} + +uint16_t fcmp_h(uint16_t v1, uint16_t v2, uint16_t op) { + float16_t v1f{v1}, v2f{v2}; + softfloat_exceptionFlags = 0; + bool nan = v1 == defaultNaNF16UI || v2 & defaultNaNF16UI; + bool snan = softfloat_isSigNaNF16UI(v1) || softfloat_isSigNaNF16UI(v2); + switch(op) { + case 0: + if(nan | snan) { + if(snan) + softfloat_raiseFlags(softfloat_flag_invalid); + return 0; + } else + return f16_eq(v1f, v2f) ? 1 : 0; + case 1: + if(nan | snan) { + softfloat_raiseFlags(softfloat_flag_invalid); + return 0; + } else + return f16_le(v1f, v2f) ? 1 : 0; + case 2: + if(nan | snan) { + softfloat_raiseFlags(softfloat_flag_invalid); + return 0; + } else + return f16_lt(v1f, v2f) ? 1 : 0; + default: + break; + } + return -1; +} + +uint16_t fmadd_h(uint16_t v1, uint16_t v2, uint16_t v3, uint16_t op, uint8_t mode) { + uint16_t F16_SIGN = 1UL << 15; + switch(op) { + case 0: // FMADD_S + break; + case 1: // FMSUB_S + v3 ^= F16_SIGN; + break; + case 2: // FNMADD_S + v1 ^= F16_SIGN; + v3 ^= F16_SIGN; + break; + case 3: // FNMSUB_S + v1 ^= F16_SIGN; + break; + } + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float16_t res = softfloat_mulAddF16(v1, v2, v3, 0); + return res.v; +} + +uint16_t fsel_h(uint16_t v1, uint16_t v2, uint16_t op) { + softfloat_exceptionFlags = 0; + bool v1_nan = (v1 & defaultNaNF16UI) == defaultNaNF16UI; + bool v2_nan = (v2 & defaultNaNF16UI) == defaultNaNF16UI; + bool v1_snan = softfloat_isSigNaNF16UI(v1); + bool v2_snan = softfloat_isSigNaNF16UI(v2); + if(v1_snan || v2_snan) + softfloat_raiseFlags(softfloat_flag_invalid); + if(v1_nan || v1_snan) + return (v2_nan || v2_snan) ? defaultNaNF16UI : v2; + else if(v2_nan || v2_snan) + return v1; + else { + if((v1 & 0x7fff) == 0 && (v2 & 0x7fff) == 0) { + return op == 0 ? ((v1 & 0x8000) ? v1 : v2) : ((v1 & 0x8000) ? v2 : v1); + } else { + float16_t v1f{v1}, v2f{v2}; + return op == 0 ? (f16_lt(v1f, v2f) ? v1 : v2) : (f16_lt(v1f, v2f) ? v2 : v1); + } + } +} + +uint16_t fclass_h(uint16_t v1) { + + float16_t a{v1}; + union ui16_f16 uA; + uint_fast16_t uiA; + + uA.f = a; + uiA = uA.ui; + + bool infOrNaN = expF16UI(uiA) == 0x1F; + bool subnormalOrZero = expF16UI(uiA) == 0; + bool sign = signF16UI(uiA); + bool fracZero = fracF16UI(uiA) == 0; + bool isNaN = isNaNF16UI(uiA); + bool isSNaN = softfloat_isSigNaNF16UI(uiA); + + return (sign && infOrNaN && fracZero) << 0 | (sign && !infOrNaN && !subnormalOrZero) << 1 | + (sign && subnormalOrZero && !fracZero) << 2 | (sign && subnormalOrZero && fracZero) << 3 | (!sign && infOrNaN && fracZero) << 7 | + (!sign && !infOrNaN && !subnormalOrZero) << 6 | (!sign && subnormalOrZero && !fracZero) << 5 | + (!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9; +} + +uint16_t frsqrt7_h(uint16_t v) { + bool subnormal = false; + uint16_t ret_val = 0; + if(rsqrt_check(fclass_h(v), subnormal, ret_val)) { + return ret_val; + } + uint16_t sig = fracF64UI(v); + int16_t exp = expF64UI(v); + uint16_t sign = signF64UI(v); + unsigned constexpr e = 5; + unsigned constexpr s = 10; + return frsqrt7_general(s, e, sign, exp, sig, subnormal); +} + uint16_t frec7_h(uint16_t v, uint8_t mode) { bool subnormal = false; uint64_t ret_val = 0; @@ -856,6 +391,178 @@ uint16_t frec7_h(uint16_t v, uint8_t mode) { softfloat_exceptionFlags |= (softfloat_flag_inexact | softfloat_flag_overflow); return ret_val; } + +uint16_t unbox_h(uint8_t FLEN, uint64_t v) { + uint64_t mask = 0; + switch(FLEN) { + case 32: { + mask = std::numeric_limits::max() & ~((uint64_t)std::numeric_limits::max()); + break; + } + case 64: { + mask = std::numeric_limits::max() & ~((uint64_t)std::numeric_limits::max()); + break; + } + default: + break; + } + if((v & mask) != mask) + return defaultNaNF16UI; + else + return v & std::numeric_limits::max(); +} + +uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode) { + float32_t v1f{v1}, v2f{v2}; + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float32_t r = f32_add(v1f, v2f); + return r.v; +} + +uint32_t fsub_s(uint32_t v1, uint32_t v2, uint8_t mode) { + float32_t v1f{v1}, v2f{v2}; + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float32_t r = f32_sub(v1f, v2f); + return r.v; +} + +uint32_t fmul_s(uint32_t v1, uint32_t v2, uint8_t mode) { + float32_t v1f{v1}, v2f{v2}; + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float32_t r = f32_mul(v1f, v2f); + return r.v; +} + +uint32_t fdiv_s(uint32_t v1, uint32_t v2, uint8_t mode) { + float32_t v1f{v1}, v2f{v2}; + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float32_t r = f32_div(v1f, v2f); + return r.v; +} + +uint32_t fsqrt_s(uint32_t v1, uint8_t mode) { + float32_t v1f{v1}; + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float32_t r = f32_sqrt(v1f); + return r.v; +} + +uint32_t fcmp_s(uint32_t v1, uint32_t v2, uint32_t op) { + float32_t v1f{v1}, v2f{v2}; + softfloat_exceptionFlags = 0; + bool nan = v1 == defaultNaNF32UI || v2 == defaultNaNF32UI; + bool snan = softfloat_isSigNaNF32UI(v1) || softfloat_isSigNaNF32UI(v2); + switch(op) { + case 0: + if(nan | snan) { + if(snan) + softfloat_raiseFlags(softfloat_flag_invalid); + return 0; + } else + return f32_eq(v1f, v2f) ? 1 : 0; + case 1: + if(nan | snan) { + softfloat_raiseFlags(softfloat_flag_invalid); + return 0; + } else + return f32_le(v1f, v2f) ? 1 : 0; + case 2: + if(nan | snan) { + softfloat_raiseFlags(softfloat_flag_invalid); + return 0; + } else + return f32_lt(v1f, v2f) ? 1 : 0; + default: + break; + } + return -1; +} + +uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mode) { + uint32_t F32_SIGN = 1UL << 31; + switch(op) { + case 0: // FMADD_S + break; + case 1: // FMSUB_S + v3 ^= F32_SIGN; + break; + case 2: // FNMADD_S + v1 ^= F32_SIGN; + v3 ^= F32_SIGN; + break; + case 3: // FNMSUB_S + v1 ^= F32_SIGN; + break; + } + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float32_t res = softfloat_mulAddF32(v1, v2, v3, 0); + return res.v; +} + +uint32_t fsel_s(uint32_t v1, uint32_t v2, uint32_t op) { + softfloat_exceptionFlags = 0; + bool v1_nan = (v1 & defaultNaNF32UI) == defaultNaNF32UI; + bool v2_nan = (v2 & defaultNaNF32UI) == defaultNaNF32UI; + bool v1_snan = softfloat_isSigNaNF32UI(v1); + bool v2_snan = softfloat_isSigNaNF32UI(v2); + if(v1_snan || v2_snan) + softfloat_raiseFlags(softfloat_flag_invalid); + if(v1_nan || v1_snan) + return (v2_nan || v2_snan) ? defaultNaNF32UI : v2; + else if(v2_nan || v2_snan) + return v1; + else { + if((v1 & 0x7fffffff) == 0 && (v2 & 0x7fffffff) == 0) { + return op == 0 ? ((v1 & 0x80000000) ? v1 : v2) : ((v1 & 0x80000000) ? v2 : v1); + } else { + float32_t v1f{v1}, v2f{v2}; + return op == 0 ? (f32_lt(v1f, v2f) ? v1 : v2) : (f32_lt(v1f, v2f) ? v2 : v1); + } + } +} + +uint32_t fclass_s(uint32_t v1) { + + float32_t a{v1}; + union ui32_f32 uA; + uint_fast32_t uiA; + + uA.f = a; + uiA = uA.ui; + + bool infOrNaN = expF32UI(uiA) == 0xFF; + bool subnormalOrZero = expF32UI(uiA) == 0; + bool sign = signF32UI(uiA); + bool fracZero = fracF32UI(uiA) == 0; + bool isNaN = isNaNF32UI(uiA); + bool isSNaN = softfloat_isSigNaNF32UI(uiA); + + return (sign && infOrNaN && fracZero) << 0 | (sign && !infOrNaN && !subnormalOrZero) << 1 | + (sign && subnormalOrZero && !fracZero) << 2 | (sign && subnormalOrZero && fracZero) << 3 | (!sign && infOrNaN && fracZero) << 7 | + (!sign && !infOrNaN && !subnormalOrZero) << 6 | (!sign && subnormalOrZero && !fracZero) << 5 | + (!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9; +} + +uint32_t frsqrt7_s(uint32_t v) { + bool subnormal = false; + uint32_t ret_val = 0; + if(rsqrt_check(fclass_s(v), subnormal, ret_val)) { + return ret_val; + } + uint32_t sig = fracF32UI(v); + int exp = expF32UI(v); + uint32_t sign = signF32UI(v); + unsigned constexpr e = 8; + unsigned constexpr s = 23; + return frsqrt7_general(s, e, sign, exp, sig, subnormal); +} + uint32_t frec7_s(uint32_t v, uint8_t mode) { bool subnormal = false; uint64_t ret_val = 0; @@ -871,6 +578,180 @@ uint32_t frec7_s(uint32_t v, uint8_t mode) { softfloat_exceptionFlags |= (softfloat_flag_inexact | softfloat_flag_overflow); return ret_val; } + +uint32_t unbox_s(uint8_t FLEN, uint64_t v) { + uint64_t mask = 0; + switch(FLEN) { + case 32: { + return v; + } + case 64: { + mask = std::numeric_limits::max() & ~((uint64_t)std::numeric_limits::max()); + break; + } + default: + break; + } + if((v & mask) != mask) + return defaultNaNF32UI; + else + return v & std::numeric_limits::max(); +} + +uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode) { + bool nan = v1 == defaultNaNF32UI; + bool snan = softfloat_isSigNaNF32UI(v1); + float64_t v1f{v1}, v2f{v2}; + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float64_t r = f64_add(v1f, v2f); + return r.v; +} + +uint64_t fsub_d(uint64_t v1, uint64_t v2, uint8_t mode) { + float64_t v1f{v1}, v2f{v2}; + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float64_t r = f64_sub(v1f, v2f); + return r.v; +} + +uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode) { + float64_t v1f{v1}, v2f{v2}; + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float64_t r = f64_mul(v1f, v2f); + return r.v; +} + +uint64_t fdiv_d(uint64_t v1, uint64_t v2, uint8_t mode) { + float64_t v1f{v1}, v2f{v2}; + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float64_t r = f64_div(v1f, v2f); + return r.v; +} + +uint64_t fsqrt_d(uint64_t v1, uint8_t mode) { + float64_t v1f{v1}; + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float64_t r = f64_sqrt(v1f); + return r.v; +} + +uint64_t fcmp_d(uint64_t v1, uint64_t v2, uint32_t op) { + float64_t v1f{v1}, v2f{v2}; + softfloat_exceptionFlags = 0; + bool nan = v1 == defaultNaNF64UI || v2 == defaultNaNF64UI; + bool snan = softfloat_isSigNaNF64UI(v1) || softfloat_isSigNaNF64UI(v2); + switch(op) { + case 0: + if(nan | snan) { + if(snan) + softfloat_raiseFlags(softfloat_flag_invalid); + return 0; + } else + return f64_eq(v1f, v2f) ? 1 : 0; + case 1: + if(nan | snan) { + softfloat_raiseFlags(softfloat_flag_invalid); + return 0; + } else + return f64_le(v1f, v2f) ? 1 : 0; + case 2: + if(nan | snan) { + softfloat_raiseFlags(softfloat_flag_invalid); + return 0; + } else + return f64_lt(v1f, v2f) ? 1 : 0; + default: + break; + } + return -1; +} + +uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode) { + uint64_t F64_SIGN = 1ULL << 63; + switch(op) { + case 0: // FMADD_D + break; + case 1: // FMSUB_D + v3 ^= F64_SIGN; + break; + case 2: // FNMADD_D + v1 ^= F64_SIGN; + v3 ^= F64_SIGN; + break; + case 3: // FNMSUB_D + v1 ^= F64_SIGN; + break; + } + softfloat_roundingMode = mode; + softfloat_exceptionFlags = 0; + float64_t res = softfloat_mulAddF64(v1, v2, v3, 0); + return res.v; +} + +uint64_t fsel_d(uint64_t v1, uint64_t v2, uint32_t op) { + softfloat_exceptionFlags = 0; + bool v1_nan = (v1 & defaultNaNF64UI) == defaultNaNF64UI; + bool v2_nan = (v2 & defaultNaNF64UI) == defaultNaNF64UI; + bool v1_snan = softfloat_isSigNaNF64UI(v1); + bool v2_snan = softfloat_isSigNaNF64UI(v2); + if(v1_snan || v2_snan) + softfloat_raiseFlags(softfloat_flag_invalid); + if(v1_nan || v1_snan) + return (v2_nan || v2_snan) ? defaultNaNF64UI : v2; + else if(v2_nan || v2_snan) + return v1; + else { + if((v1 & std::numeric_limits::max()) == 0 && (v2 & std::numeric_limits::max()) == 0) { + return op == 0 ? ((v1 & std::numeric_limits::min()) ? v1 : v2) + : ((v1 & std::numeric_limits::min()) ? v2 : v1); + } else { + float64_t v1f{v1}, v2f{v2}; + return op == 0 ? (f64_lt(v1f, v2f) ? v1 : v2) : (f64_lt(v1f, v2f) ? v2 : v1); + } + } +} + +uint64_t fclass_d(uint64_t v1) { + + float64_t a{v1}; + union ui64_f64 uA; + uint_fast64_t uiA; + + uA.f = a; + uiA = uA.ui; + + bool infOrNaN = expF64UI(uiA) == 0x7FF; + bool subnormalOrZero = expF64UI(uiA) == 0; + bool sign = signF64UI(uiA); + bool fracZero = fracF64UI(uiA) == 0; + bool isNaN = isNaNF64UI(uiA); + bool isSNaN = softfloat_isSigNaNF64UI(uiA); + + return (sign && infOrNaN && fracZero) << 0 | (sign && !infOrNaN && !subnormalOrZero) << 1 | + (sign && subnormalOrZero && !fracZero) << 2 | (sign && subnormalOrZero && fracZero) << 3 | (!sign && infOrNaN && fracZero) << 7 | + (!sign && !infOrNaN && !subnormalOrZero) << 6 | (!sign && subnormalOrZero && !fracZero) << 5 | + (!sign && subnormalOrZero && fracZero) << 4 | (isNaN && isSNaN) << 8 | (isNaN && !isSNaN) << 9; +} + +uint64_t frsqrt7_d(uint64_t v) { + bool subnormal = false; + uint64_t ret_val = 0; + if(rsqrt_check(fclass_d(v), subnormal, ret_val)) { + return ret_val; + } + uint64_t sig = fracF64UI(v); + int exp = expF64UI(v); + uint64_t sign = signF64UI(v); + unsigned constexpr e = 11; + unsigned constexpr s = 52; + return frsqrt7_general(s, e, sign, exp, sig, subnormal); +} + uint64_t frec7_d(uint64_t v, uint8_t mode) { bool subnormal = false; uint64_t ret_val = 0; @@ -887,6 +768,22 @@ uint64_t frec7_d(uint64_t v, uint8_t mode) { return ret_val; } +uint64_t unbox_d(uint8_t FLEN, uint64_t v) { + uint64_t mask = 0; + switch(FLEN) { + case 64: { + return v; + break; + } + default: + break; + } + if((v & mask) != mask) + return defaultNaNF64UI; + else + return v & std::numeric_limits::max(); +} + // conversion: float to float uint32_t f16tof32(uint16_t val, uint8_t rm) { softfloat_exceptionFlags = 0; @@ -920,6 +817,7 @@ uint32_t f64tof32(uint64_t val, uint8_t rm) { softfloat_roundingMode = rm; return f64_to_f32(float64_t{val}).v; } + // conversions: float to unsigned uint32_t f16toui32(uint16_t v, uint8_t rm) { softfloat_exceptionFlags = 0; @@ -931,6 +829,26 @@ uint64_t f16toui64(uint16_t v, uint8_t rm) { softfloat_roundingMode = rm; return f16_to_ui64(float16_t{v}, rm, true); } +uint32_t f32toui32(uint32_t v, uint8_t rm) { + softfloat_exceptionFlags = 0; + softfloat_roundingMode = rm; + return f32_to_ui32(float32_t{v}, rm, true); +} +uint64_t f32toui64(uint32_t v, uint8_t rm) { + softfloat_exceptionFlags = 0; + softfloat_roundingMode = rm; + return f32_to_ui64(float32_t{v}, rm, true); +} +uint32_t f64toui32(uint64_t v, uint8_t rm) { + softfloat_exceptionFlags = 0; + softfloat_roundingMode = rm; + return f64_to_ui32(float64_t{v}, rm, true); +} +uint64_t f64toui64(uint64_t v, uint8_t rm) { + softfloat_exceptionFlags = 0; + softfloat_roundingMode = rm; + return f64_to_ui64(float64_t{v}, rm, true); +} // conversions: float to signed uint32_t f16toi32(uint16_t v, uint8_t rm) { @@ -943,6 +861,26 @@ uint64_t f16toi64(uint16_t v, uint8_t rm) { softfloat_roundingMode = rm; return f16_to_i64(float16_t{v}, rm, true); } +uint32_t f32toi32(uint32_t v, uint8_t rm) { + softfloat_exceptionFlags = 0; + softfloat_roundingMode = rm; + return f32_to_i32(float32_t{v}, rm, true); +} +uint64_t f32toi64(uint32_t v, uint8_t rm) { + softfloat_exceptionFlags = 0; + softfloat_roundingMode = rm; + return f32_to_i64(float32_t{v}, rm, true); +} +uint32_t f64toi32(uint64_t v, uint8_t rm) { + softfloat_exceptionFlags = 0; + softfloat_roundingMode = rm; + return f64_to_i32(float64_t{v}, rm, true); +} +uint64_t f64toi64(uint64_t v, uint8_t rm) { + softfloat_exceptionFlags = 0; + softfloat_roundingMode = rm; + return f64_to_i64(float64_t{v}, rm, true); +} // conversions: unsigned to float uint16_t ui32tof16(uint32_t v, uint8_t rm) { @@ -955,6 +893,26 @@ uint16_t ui64tof16(uint64_t v, uint8_t rm) { softfloat_roundingMode = rm; return ui64_to_f16(v).v; } +uint32_t ui32tof32(uint32_t v, uint8_t rm) { + softfloat_exceptionFlags = 0; + softfloat_roundingMode = rm; + return ui32_to_f32(v).v; +} +uint32_t ui64tof32(uint64_t v, uint8_t rm) { + softfloat_exceptionFlags = 0; + softfloat_roundingMode = rm; + return ui64_to_f32(v).v; +} +uint64_t ui32tof64(uint32_t v, uint8_t rm) { + softfloat_exceptionFlags = 0; + softfloat_roundingMode = rm; + return ui32_to_f64(v).v; +} +uint64_t ui64tof64(uint64_t v, uint8_t rm) { + softfloat_exceptionFlags = 0; + softfloat_roundingMode = rm; + return ui64_to_f64(v).v; +} // conversions: signed to float uint16_t i32tof16(uint32_t v, uint8_t rm) { @@ -966,4 +924,25 @@ uint16_t i64tof16(uint64_t v, uint8_t rm) { softfloat_exceptionFlags = 0; softfloat_roundingMode = rm; return i64_to_f16(v).v; +} +uint32_t i32tof32(uint32_t v, uint8_t rm) { + softfloat_exceptionFlags = 0; + softfloat_roundingMode = rm; + return i32_to_f32(v).v; +} +uint32_t i64tof32(uint64_t v, uint8_t rm) { + softfloat_exceptionFlags = 0; + softfloat_roundingMode = rm; + return i64_to_f32(v).v; +} +uint64_t i32tof64(uint32_t v, uint8_t rm) { + softfloat_exceptionFlags = 0; + softfloat_roundingMode = rm; + return i32_to_f64(v).v; +} +uint64_t i64tof64(uint64_t v, uint8_t rm) { + softfloat_exceptionFlags = 0; + softfloat_roundingMode = rm; + return i64_to_f64(v).v; +} } \ No newline at end of file diff --git a/src/vm/fp_functions.h b/src/vm/fp_functions.h index 964fa11..1cf749d 100644 --- a/src/vm/fp_functions.h +++ b/src/vm/fp_functions.h @@ -39,6 +39,7 @@ extern "C" { uint32_t fget_flags(); + // half precision uint16_t fadd_h(uint16_t v1, uint16_t v2, uint8_t mode); uint16_t fsub_h(uint16_t v1, uint16_t v2, uint8_t mode); @@ -46,7 +47,6 @@ uint16_t fmul_h(uint16_t v1, uint16_t v2, uint8_t mode); uint16_t fdiv_h(uint16_t v1, uint16_t v2, uint8_t mode); uint16_t fsqrt_h(uint16_t v1, uint8_t mode); uint16_t fcmp_h(uint16_t v1, uint16_t v2, uint16_t op); -uint16_t fcvt_h(uint16_t v1, uint16_t op, uint8_t mode); uint16_t fmadd_h(uint16_t v1, uint16_t v2, uint16_t v3, uint16_t op, uint8_t mode); uint16_t fsel_h(uint16_t v1, uint16_t v2, uint16_t op); uint16_t fsqrt_h(uint16_t v1, uint8_t mode); @@ -62,13 +62,12 @@ uint32_t fmul_s(uint32_t v1, uint32_t v2, uint8_t mode); uint32_t fdiv_s(uint32_t v1, uint32_t v2, uint8_t mode); uint32_t fsqrt_s(uint32_t v1, uint8_t mode); uint32_t fcmp_s(uint32_t v1, uint32_t v2, uint32_t op); -uint32_t fcvt_s(uint32_t v1, uint32_t op, uint8_t mode); uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mode); uint32_t fsel_s(uint32_t v1, uint32_t v2, uint32_t op); uint32_t fclass_s(uint32_t v1); uint32_t frsqrt7_s(uint32_t v); uint32_t frec7_s(uint32_t v, uint8_t mode); -uint32_t unbox_s(uint64_t v); +uint32_t unbox_s(uint8_t FLEN, uint64_t v); // double precision uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode); @@ -77,43 +76,51 @@ uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode); uint64_t fdiv_d(uint64_t v1, uint64_t v2, uint8_t mode); uint64_t fsqrt_d(uint64_t v1, uint8_t mode); uint64_t fcmp_d(uint64_t v1, uint64_t v2, uint32_t op); -uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode); uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode); uint64_t fsel_d(uint64_t v1, uint64_t v2, uint32_t op); uint64_t fclass_d(uint64_t v1); uint64_t frsqrt7_d(uint64_t v); uint64_t frec7_d(uint64_t v, uint8_t mode); - -// conversions -uint32_t fconv_d2f(uint64_t v1, uint8_t mode); -uint64_t fconv_f2d(uint32_t v1, uint8_t mode); -uint64_t fcvt_32_64(uint32_t v1, uint32_t op, uint8_t mode); -uint32_t fcvt_64_32(uint64_t v1, uint32_t op, uint8_t mode); +uint64_t unbox_d(uint8_t FLEN, uint64_t v); // conversion: float to float uint32_t f16tof32(uint16_t val, uint8_t rm); uint64_t f16tof64(uint16_t val, uint8_t rm); - uint16_t f32tof16(uint32_t val, uint8_t rm); uint64_t f32tof64(uint32_t val, uint8_t rm); - uint16_t f64tof16(uint64_t val, uint8_t rm); uint32_t f64tof32(uint64_t val, uint8_t rm); // conversions: float to unsigned uint32_t f16toui32(uint16_t v, uint8_t rm); uint64_t f16toui64(uint16_t v, uint8_t rm); +uint32_t f32toui32(uint32_t v, uint8_t rm); +uint64_t f32toui64(uint32_t v, uint8_t rm); +uint32_t f64toui32(uint64_t v, uint8_t rm); +uint64_t f64toui64(uint64_t v, uint8_t rm); // conversions: float to signed uint32_t f16toi32(uint16_t v, uint8_t rm); uint64_t f16toi64(uint16_t v, uint8_t rm); +uint32_t f32toi32(uint32_t v, uint8_t rm); +uint64_t f32toi64(uint32_t v, uint8_t rm); +uint32_t f64toi32(uint64_t v, uint8_t rm); +uint64_t f64toi64(uint64_t v, uint8_t rm); // conversions: unsigned to float uint16_t ui32tof16(uint32_t v, uint8_t rm); uint16_t ui64tof16(uint64_t v, uint8_t rm); +uint32_t ui32tof32(uint32_t v, uint8_t rm); +uint32_t ui64tof32(uint64_t v, uint8_t rm); +uint64_t ui32tof64(uint32_t v, uint8_t rm); +uint64_t ui64tof64(uint64_t v, uint8_t rm); // conversions: signed to float uint16_t i32tof16(uint32_t v, uint8_t rm); uint16_t i64tof16(uint64_t v, uint8_t rm); +uint32_t i32tof32(uint32_t v, uint8_t rm); +uint32_t i64tof32(uint64_t v, uint8_t rm); +uint64_t i32tof64(uint32_t v, uint8_t rm); +uint64_t i64tof64(uint64_t v, uint8_t rm); } #endif /* _VM_FP_FUNCTIONS_H_ */ diff --git a/src/vm/vector_functions.hpp b/src/vm/vector_functions.hpp index d308a50..f5320dd 100644 --- a/src/vm/vector_functions.hpp +++ b/src/vm/vector_functions.hpp @@ -1329,69 +1329,21 @@ template dest_elem_size_t template dest_elem_size_t fp_i_to_f(uint8_t, src_elem_size_t); template dest_elem_t fp_f_to_f(uint8_t rm, src_elem_t val); -template <> inline uint16_t fp_f_to_ui(uint8_t rm, uint16_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return f16_to_ui32(float16_t{v2}, rm, true); -} -template <> inline uint32_t fp_f_to_ui(uint8_t rm, uint32_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return f32_to_ui32(float32_t{v2}, rm, true); -} -template <> inline uint64_t fp_f_to_ui(uint8_t rm, uint64_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return f64_to_ui64(float64_t{v2}, rm, true); -} +template <> inline uint16_t fp_f_to_ui(uint8_t rm, uint16_t v2) { return f16toui32(v2, rm); } +template <> inline uint32_t fp_f_to_ui(uint8_t rm, uint32_t v2) { return f32toui32(v2, rm); } +template <> inline uint64_t fp_f_to_ui(uint8_t rm, uint64_t v2) { return f64toui64(v2, rm); } -template <> inline uint16_t fp_f_to_i(uint8_t rm, uint16_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return f16_to_i32(float16_t{v2}, rm, true); -} -template <> inline uint32_t fp_f_to_i(uint8_t rm, uint32_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return f32_to_i32(float32_t{v2}, rm, true); -} -template <> inline uint64_t fp_f_to_i(uint8_t rm, uint64_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return f64_to_i64(float64_t{v2}, rm, true); -} +template <> inline uint16_t fp_f_to_i(uint8_t rm, uint16_t v2) { return f16toi32(v2, rm); } +template <> inline uint32_t fp_f_to_i(uint8_t rm, uint32_t v2) { return f32toi32(v2, rm); } +template <> inline uint64_t fp_f_to_i(uint8_t rm, uint64_t v2) { return f64toi64(v2, rm); } -template <> inline uint16_t fp_ui_to_f(uint8_t rm, uint16_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return ui32_to_f16(v2).v; -} -template <> inline uint32_t fp_ui_to_f(uint8_t rm, uint32_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return ui32_to_f32(v2).v; -} -template <> inline uint64_t fp_ui_to_f(uint8_t rm, uint64_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return ui64_to_f64(v2).v; -} +template <> inline uint16_t fp_ui_to_f(uint8_t rm, uint16_t v2) { return ui32tof16(v2, rm); } +template <> inline uint32_t fp_ui_to_f(uint8_t rm, uint32_t v2) { return ui32tof32(v2, rm); } +template <> inline uint64_t fp_ui_to_f(uint8_t rm, uint64_t v2) { return ui64tof64(v2, rm); } -template <> inline uint16_t fp_i_to_f(uint8_t rm, uint16_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return i32_to_f16(static_cast(v2)).v; -} -template <> inline uint32_t fp_i_to_f(uint8_t rm, uint32_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return i32_to_f32(v2).v; -} -template <> inline uint64_t fp_i_to_f(uint8_t rm, uint64_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return i64_to_f64(v2).v; -} +template <> inline uint16_t fp_i_to_f(uint8_t rm, uint16_t v2) { return i32tof16(v2, rm); } +template <> inline uint32_t fp_i_to_f(uint8_t rm, uint32_t v2) { return i32tof32(v2, rm); } +template <> inline uint64_t fp_i_to_f(uint8_t rm, uint64_t v2) { return i64tof64(v2, rm); } template std::function get_fp_unary_fn(unsigned encoding_space, unsigned unary_op) { if(encoding_space == 0b010011) // VFUNARY1 @@ -1481,62 +1433,22 @@ void fp_vector_unary_op(uint8_t* V, unsigned encoding_space, unsigned unary_op, template <> inline uint16_t fp_f_to_ui(uint8_t rm, uint8_t v2) { throw new std::runtime_error("Attempting illegal widening conversion"); } -template <> inline uint32_t fp_f_to_ui(uint8_t rm, uint16_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return f16_to_ui32(float16_t{v2}, rm, true); -} -template <> inline uint64_t fp_f_to_ui(uint8_t rm, uint32_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return f32_to_ui64(float32_t{v2}, rm, true); -} +template <> inline uint32_t fp_f_to_ui(uint8_t rm, uint16_t v2) { return f16toui32(v2, rm); } +template <> inline uint64_t fp_f_to_ui(uint8_t rm, uint32_t v2) { return f32toui64(v2, rm); } template <> inline uint16_t fp_f_to_i(uint8_t rm, uint8_t v2) { throw new std::runtime_error("Attempting illegal widening conversion"); } -template <> inline uint32_t fp_f_to_i(uint8_t rm, uint16_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return f16_to_i32(float16_t{v2}, rm, true); -} -template <> inline uint64_t fp_f_to_i(uint8_t rm, uint32_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return f32_to_i64(float32_t{v2}, rm, true); -} +template <> inline uint32_t fp_f_to_i(uint8_t rm, uint16_t v2) { return f16toi32(v2, rm); } +template <> inline uint64_t fp_f_to_i(uint8_t rm, uint32_t v2) { return f32toi64(v2, rm); } -template <> inline uint16_t fp_ui_to_f(uint8_t rm, uint8_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return ui32_to_f16(v2).v; -} -template <> inline uint32_t fp_ui_to_f(uint8_t rm, uint16_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return ui32_to_f32(v2).v; -} -template <> inline uint64_t fp_ui_to_f(uint8_t rm, uint32_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return ui32_to_f64(v2).v; -} +template <> inline uint16_t fp_ui_to_f(uint8_t rm, uint8_t v2) { return ui32tof16(v2, rm); } +template <> inline uint32_t fp_ui_to_f(uint8_t rm, uint16_t v2) { return ui32tof32(v2, rm); } +template <> inline uint64_t fp_ui_to_f(uint8_t rm, uint32_t v2) { return ui32tof64(v2, rm); } -template <> inline uint16_t fp_i_to_f(uint8_t rm, uint8_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return i32_to_f16(static_cast(v2)).v; -} -template <> inline uint32_t fp_i_to_f(uint8_t rm, uint16_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return i32_to_f32(static_cast(v2)).v; -} -template <> inline uint64_t fp_i_to_f(uint8_t rm, uint32_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return i32_to_f64(v2).v; -} +template <> inline uint16_t fp_i_to_f(uint8_t rm, uint8_t v2) { return i32tof16(v2, rm); } +template <> inline uint32_t fp_i_to_f(uint8_t rm, uint16_t v2) { return i32tof32(v2, rm); } +template <> inline uint64_t fp_i_to_f(uint8_t rm, uint32_t v2) { return i32tof64(v2, rm); } template <> inline uint16_t fp_f_to_f(uint8_t rm, uint8_t val) { throw new std::runtime_error("Attempting illegal widening conversion"); @@ -1605,65 +1517,25 @@ void fp_vector_unary_w(uint8_t* V, unsigned unary_op, uint64_t vl, uint64_t vsta vd_view[idx] = agnostic_behavior(vd_view[idx]); } -template <> inline uint8_t fp_f_to_ui(uint8_t rm, uint16_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return f16_to_ui32(float16_t{v2}, rm, true); -} -template <> inline uint16_t fp_f_to_ui(uint8_t rm, uint32_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return f32_to_ui32(float32_t{v2}, rm, true); -} -template <> inline uint32_t fp_f_to_ui(uint8_t rm, uint64_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return f64_to_ui32(float64_t{v2}, rm, true); -} +template <> inline uint8_t fp_f_to_ui(uint8_t rm, uint16_t v2) { return f16toui32(v2, rm); } +template <> inline uint16_t fp_f_to_ui(uint8_t rm, uint32_t v2) { return f32toui32(v2, rm); } +template <> inline uint32_t fp_f_to_ui(uint8_t rm, uint64_t v2) { return f64toui32(v2, rm); } -template <> inline uint8_t fp_f_to_i(uint8_t rm, uint16_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return f16_to_i32(float16_t{v2}, rm, true); -} -template <> inline uint16_t fp_f_to_i(uint8_t rm, uint32_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return f32_to_i32(float32_t{v2}, rm, true); -} -template <> inline uint32_t fp_f_to_i(uint8_t rm, uint64_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return f64_to_i32(float64_t{v2}, rm, true); -} +template <> inline uint8_t fp_f_to_i(uint8_t rm, uint16_t v2) { return f16toi32(v2, rm); } +template <> inline uint16_t fp_f_to_i(uint8_t rm, uint32_t v2) { return f32toi32(v2, rm); } +template <> inline uint32_t fp_f_to_i(uint8_t rm, uint64_t v2) { return f64toi32(v2, rm); } template <> inline uint8_t fp_ui_to_f(uint8_t rm, uint16_t v2) { throw new std::runtime_error("Attempting illegal narrowing conversion"); } -template <> inline uint16_t fp_ui_to_f(uint8_t rm, uint32_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return ui32_to_f16(v2).v; -} -template <> inline uint32_t fp_ui_to_f(uint8_t rm, uint64_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return ui64_to_f32(v2).v; -} +template <> inline uint16_t fp_ui_to_f(uint8_t rm, uint32_t v2) { return ui32tof16(v2, rm); } +template <> inline uint32_t fp_ui_to_f(uint8_t rm, uint64_t v2) { return ui64tof32(v2, rm); } template <> inline uint8_t fp_i_to_f(uint8_t rm, uint16_t v2) { throw new std::runtime_error("Attempting illegal narrowing conversion"); } -template <> inline uint16_t fp_i_to_f(uint8_t rm, uint32_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return i32_to_f16(v2).v; -} -template <> inline uint32_t fp_i_to_f(uint8_t rm, uint64_t v2) { - softfloat_exceptionFlags = 0; - softfloat_roundingMode = rm; - return i64_to_f32(v2).v; -} +template <> inline uint16_t fp_i_to_f(uint8_t rm, uint32_t v2) { return i32tof16(v2, rm); } +template <> inline uint32_t fp_i_to_f(uint8_t rm, uint64_t v2) { return i64tof32(v2, rm); } template <> inline uint8_t fp_f_to_f(uint8_t rm, uint16_t val) { throw new std::runtime_error("Attempting illegal narrowing conversion");