diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/fp/fp-test-log2.c | 118 | ||||
-rw-r--r-- | tests/fp/fp-test.c | 9 | ||||
-rw-r--r-- | tests/fp/meson.build | 27 | ||||
-rw-r--r-- | tests/fp/wrap.c.inc | 2 |
4 files changed, 143 insertions, 13 deletions
diff --git a/tests/fp/fp-test-log2.c b/tests/fp/fp-test-log2.c new file mode 100644 index 0000000000..4eae93eb7c --- /dev/null +++ b/tests/fp/fp-test-log2.c @@ -0,0 +1,118 @@ +/* + * fp-test-log2.c - test QEMU's softfloat log2 + * + * Copyright (C) 2020, Linaro, Ltd. + * + * License: GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#ifndef HW_POISON_H +#error Must define HW_POISON_H to work around TARGET_* poisoning +#endif + +#include "qemu/osdep.h" +#include "qemu/cutils.h" +#include <math.h> +#include "fpu/softfloat.h" + +typedef union { + double d; + float64 i; +} ufloat64; + +static int errors; + +static void compare(ufloat64 test, ufloat64 real, ufloat64 soft, bool exact) +{ + int msb; + uint64_t ulp = UINT64_MAX; + + if (real.i == soft.i) { + return; + } + msb = 63 - __builtin_clzll(real.i ^ soft.i); + + if (msb < 52) { + if (real.i > soft.i) { + ulp = real.i - soft.i; + } else { + ulp = soft.i - real.i; + } + } + + /* glibc allows 3 ulp error in its libm-test-ulps; allow 4 here */ + if (!exact && ulp <= 4) { + return; + } + + printf("test: %016" PRIx64 " %+.13a\n" + " sf: %016" PRIx64 " %+.13a\n" + "libm: %016" PRIx64 " %+.13a\n", + test.i, test.d, soft.i, soft.d, real.i, real.d); + + if (msb == 63) { + printf("Error in sign!\n\n"); + } else if (msb >= 52) { + printf("Error in exponent: %d\n\n", + (int)(soft.i >> 52) - (int)(real.i >> 52)); + } else { + printf("Error in fraction: %" PRIu64 " ulp\n\n", ulp); + } + + if (++errors == 20) { + exit(1); + } +} + +int main(int ac, char **av) +{ + ufloat64 test, real, soft; + float_status qsf = {0}; + int i; + + set_float_rounding_mode(float_round_nearest_even, &qsf); + + test.d = 0.0; + real.d = -__builtin_inf(); + soft.i = float64_log2(test.i, &qsf); + compare(test, real, soft, true); + + test.d = 1.0; + real.d = 0.0; + soft.i = float64_log2(test.i, &qsf); + compare(test, real, soft, true); + + test.d = 2.0; + real.d = 1.0; + soft.i = float64_log2(test.i, &qsf); + compare(test, real, soft, true); + + test.d = 4.0; + real.d = 2.0; + soft.i = float64_log2(test.i, &qsf); + compare(test, real, soft, true); + + test.d = 0x1p64; + real.d = 64.0; + soft.i = float64_log2(test.i, &qsf); + compare(test, real, soft, true); + + test.d = __builtin_inf(); + real.d = __builtin_inf(); + soft.i = float64_log2(test.i, &qsf); + compare(test, real, soft, true); + + for (i = 0; i < 10000; ++i) { + test.d = drand48() + 1.0; /* [1.0, 2.0) */ + real.d = log2(test.d); + soft.i = float64_log2(test.i, &qsf); + compare(test, real, soft, false); + + test.d = drand48() * 100; /* [0.0, 100) */ + real.d = log2(test.d); + soft.i = float64_log2(test.i, &qsf); + compare(test, real, soft, false); + } + + return 0; +} diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c index ff131afbde..352dd71c44 100644 --- a/tests/fp/fp-test.c +++ b/tests/fp/fp-test.c @@ -963,18 +963,21 @@ static void QEMU_NORETURN run_test(void) verCases_usesExact = !!(attrs & FUNC_ARG_EXACT); for (k = 0; k < 3; k++) { - int prec80 = 32; + FloatX80RoundPrec qsf_prec80 = floatx80_precision_x; + int prec80 = 80; int l; if (k == 1) { prec80 = 64; + qsf_prec80 = floatx80_precision_d; } else if (k == 2) { - prec80 = 80; + prec80 = 32; + qsf_prec80 = floatx80_precision_s; } verCases_roundingPrecision = 0; slow_extF80_roundingPrecision = prec80; - qsf.floatx80_rounding_precision = prec80; + qsf.floatx80_rounding_precision = qsf_prec80; if (attrs & FUNC_EFF_ROUNDINGPRECISION) { verCases_roundingPrecision = prec80; diff --git a/tests/fp/meson.build b/tests/fp/meson.build index 1c3eee9955..07e2cdc8d2 100644 --- a/tests/fp/meson.build +++ b/tests/fp/meson.build @@ -556,7 +556,9 @@ softfloat_conv_tests = { 'extF80_to_f64 extF80_to_f128 ' + 'f128_to_f16', 'int-to-float': 'i32_to_f16 i64_to_f16 i32_to_f32 i64_to_f32 ' + - 'i32_to_f64 i64_to_f64 i32_to_f128 i64_to_f128', + 'i32_to_f64 i64_to_f64 ' + + 'i32_to_extF80 i64_to_extF80 ' + + 'i32_to_f128 i64_to_f128', 'uint-to-float': 'ui32_to_f16 ui64_to_f16 ui32_to_f32 ui64_to_f32 ' + 'ui32_to_f64 ui64_to_f64 ui64_to_f128 ' + 'ui32_to_extF80 ui64_to_extF80', @@ -581,7 +583,7 @@ softfloat_conv_tests = { 'extF80_to_ui64 extF80_to_ui64_r_minMag ' + 'f128_to_ui64 f128_to_ui64_r_minMag', 'round-to-integer': 'f16_roundToInt f32_roundToInt ' + - 'f64_roundToInt f128_roundToInt' + 'f64_roundToInt extF80_roundToInt f128_roundToInt' } softfloat_tests = { 'eq_signaling' : 'compare', @@ -602,24 +604,20 @@ fptest_args = ['-s', '-l', '1'] fptest_rounding_args = ['-r', 'all'] # Conversion Routines: -# FIXME: i32_to_extF80 (broken), i64_to_extF80 (broken) -# extF80_roundToInt (broken) foreach k, v : softfloat_conv_tests test('fp-test-' + k, fptest, args: fptest_args + fptest_rounding_args + v.split(), suite: ['softfloat', 'softfloat-conv']) endforeach -# FIXME: extF80_{lt_quiet, rem} (broken), -# extF80_{mulAdd} (missing) foreach k, v : softfloat_tests - extF80_broken = ['lt_quiet', 'rem'].contains(k) test('fp-test-' + k, fptest, args: fptest_args + fptest_rounding_args + - ['f16_' + k, 'f32_' + k, 'f64_' + k, 'f128_' + k] + - (extF80_broken ? [] : ['extF80_' + k]), + ['f16_' + k, 'f32_' + k, 'f64_' + k, 'f128_' + k, 'extF80_' + k], suite: ['softfloat', 'softfloat-' + v]) endforeach + +# FIXME: extF80_{mulAdd} (missing) test('fp-test-mulAdd', fptest, # no fptest_rounding_args args: fptest_args + @@ -634,3 +632,14 @@ fpbench = executable( include_directories: [sfinc, include_directories(tfdir)], c_args: fpcflags, ) + +fptestlog2 = executable( + 'fp-test-log2', + ['fp-test-log2.c', '../../fpu/softfloat.c'], + link_with: [libsoftfloat], + dependencies: [qemuutil], + include_directories: [sfinc], + c_args: fpcflags, +) +test('fp-test-log2', fptestlog2, + suite: ['softfloat', 'softfloat-ops']) diff --git a/tests/fp/wrap.c.inc b/tests/fp/wrap.c.inc index cb1bb77e4c..9ff884c140 100644 --- a/tests/fp/wrap.c.inc +++ b/tests/fp/wrap.c.inc @@ -643,7 +643,7 @@ WRAP_CMP80(qemu_extF80M_eq, floatx80_eq_quiet) WRAP_CMP80(qemu_extF80M_le, floatx80_le) WRAP_CMP80(qemu_extF80M_lt, floatx80_lt) WRAP_CMP80(qemu_extF80M_le_quiet, floatx80_le_quiet) -WRAP_CMP80(qemu_extF80M_lt_quiet, floatx80_le_quiet) +WRAP_CMP80(qemu_extF80M_lt_quiet, floatx80_lt_quiet) #undef WRAP_CMP80 #define WRAP_CMP128(name, func) \ |