From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39147) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fyOuo-0003wS-Er for qemu-devel@nongnu.org; Fri, 07 Sep 2018 18:07:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fyOui-0005Qw-Es for qemu-devel@nongnu.org; Fri, 07 Sep 2018 18:07:46 -0400 Received: from out1-smtp.messagingengine.com ([66.111.4.25]:36211) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fyOui-0005P6-2X for qemu-devel@nongnu.org; Fri, 07 Sep 2018 18:07:40 -0400 From: "Emilio G. Cota" Date: Fri, 7 Sep 2018 18:07:31 -0400 Message-Id: <20180907220731.19368-3-cota@braap.org> In-Reply-To: <20180907220731.19368-1-cota@braap.org> References: <20180907220731.19368-1-cota@braap.org> Subject: [Qemu-devel] [PATCH 2/2] tests: add floating point tests List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Peter Maydell , Aurelien Jarno , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Laurent Vivier By leveraging berkeley's softfloat and testfloat. fp-test.c is derived from testfloat's testsoftfloat.c. To ease the tracking of upstream changes to the latter file, fp-test.c keeps the original camel-case variable naming, and includes most new code via wrap.inc.c. Most changes to the original code are simple style changes, although a few hacks have been added because our implementation does not provide exactly the same features as softfloat. I've noted these hacks with XXX comments. Signed-off-by: Emilio G. Cota --- configure | 2 + tests/fp/platform.h | 41 ++ tests/fp/fp-test.c | 1052 ++++++++++++++++++++++++++++++++++++++++ tests/fp/wrap.inc.c | 599 +++++++++++++++++++++++ tests/Makefile.include | 3 + tests/fp/.gitignore | 1 + tests/fp/Makefile | 589 ++++++++++++++++++++++ 7 files changed, 2287 insertions(+) create mode 100644 tests/fp/platform.h create mode 100644 tests/fp/fp-test.c create mode 100644 tests/fp/wrap.inc.c create mode 100644 tests/fp/.gitignore create mode 100644 tests/fp/Makefile diff --git a/configure b/configure index 58862d2ae8..b02da8c0b4 100755 --- a/configure +++ b/configure @@ -7451,12 +7451,14 @@ fi # build tree in object directory in case the source is not in the current directory DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/qapi-schema tests/tcg/xtensa tests/qemu-iotests tests/vm" +DIRS="$DIRS tests/fp" DIRS="$DIRS docs docs/interop fsdev scsi" DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw" DIRS="$DIRS roms/seabios roms/vgabios" FILES="Makefile tests/tcg/Makefile qdict-test-data.txt" FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit" FILES="$FILES tests/tcg/lm32/Makefile tests/tcg/xtensa/Makefile po/Makefile" +FILES="$FILES tests/fp/Makefile" FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps" FILES="$FILES pc-bios/spapr-rtas/Makefile" FILES="$FILES pc-bios/s390-ccw/Makefile" diff --git a/tests/fp/platform.h b/tests/fp/platform.h new file mode 100644 index 0000000000..80af8a94b6 --- /dev/null +++ b/tests/fp/platform.h @@ -0,0 +1,41 @@ +#ifndef QEMU_TESTFLOAT_PLATFORM_H +#define QEMU_TESTFLOAT_PLATFORM_H +/* + * Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of + * California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions, and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions, and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the University nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "config-host.h" + +#ifndef HOST_WORDS_BIGENDIAN +#define LITTLEENDIAN 1 +/* otherwise do not define it */ +#endif + +#define INLINE static inline + +#endif /* QEMU_TESTFLOAT_PLATFORM_H */ diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c new file mode 100644 index 0000000000..58405fdd89 --- /dev/null +++ b/tests/fp/fp-test.c @@ -0,0 +1,1052 @@ +/* + * fp-test.c - test QEMU's softfloat implementation using Berkeley's Testfloat + * + * Derived from testfloat/source/testsoftfloat.c. + * + * Copyright (C) 2018, Emilio G. Cota + * Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the + * University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions, and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions, and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the University nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#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 +#include "fpu/softfloat.h" +#include "platform.h" + +#include "fail.h" +#include "slowfloat.h" +#include "functions.h" +#include "genCases.h" +#include "verCases.h" +#include "writeCase.h" +#include "testLoops.h" + +/* keep most code separate to make tracking upstream changes more easily */ +#include "wrap.inc.c" + +enum { + EXACT_FALSE = 1, + EXACT_TRUE +}; + +static void catchSIGINT(int signalCode) +{ + if (verCases_stop) { + exit(EXIT_FAILURE); + } + verCases_stop = true; +} + +static void +testFunctionInstance(int functionCode, uint_fast8_t roundingMode, bool exact) +{ + float16_t (*trueFunction_abz_f16)(float16_t, float16_t); + float16_t (*subjFunction_abz_f16)(float16_t, float16_t); + bool (*trueFunction_ab_f16_z_bool)(float16_t, float16_t); + bool (*subjFunction_ab_f16_z_bool)(float16_t, float16_t); + float32_t (*trueFunction_abz_f32)(float32_t, float32_t); + float32_t (*subjFunction_abz_f32)(float32_t, float32_t); + bool (*trueFunction_ab_f32_z_bool)(float32_t, float32_t); + bool (*subjFunction_ab_f32_z_bool)(float32_t, float32_t); + float64_t (*trueFunction_abz_f64)(float64_t, float64_t); + float64_t (*subjFunction_abz_f64)(float64_t, float64_t); + bool (*trueFunction_ab_f64_z_bool)(float64_t, float64_t); + bool (*subjFunction_ab_f64_z_bool)(float64_t, float64_t); + void (*trueFunction_abz_extF80M)( + const extFloat80_t *, const extFloat80_t *, extFloat80_t *); + void (*subjFunction_abz_extF80M)( + const extFloat80_t *, const extFloat80_t *, extFloat80_t *); + bool (*trueFunction_ab_extF80M_z_bool)( + const extFloat80_t *, const extFloat80_t *); + bool (*subjFunction_ab_extF80M_z_bool)( + const extFloat80_t *, const extFloat80_t *); + void (*trueFunction_abz_f128M)( + const float128_t *, const float128_t *, float128_t *); + void (*subjFunction_abz_f128M)( + const float128_t *, const float128_t *, float128_t *); + bool (*trueFunction_ab_f128M_z_bool)( + const float128_t *, const float128_t *); + bool (*subjFunction_ab_f128M_z_bool)( + const float128_t *, const float128_t *); + + fputs("Testing ", stderr); + verCases_writeFunctionName(stderr); + fputs(".\n", stderr); + + switch (functionCode) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + case UI32_TO_F16: + test_a_ui32_z_f16(slow_ui32_to_f16, qemu_ui32_to_f16); + break; + case UI32_TO_F32: + test_a_ui32_z_f32(slow_ui32_to_f32, qemu_ui32_to_f32); + break; + case UI32_TO_F64: + test_a_ui32_z_f64(slow_ui32_to_f64, qemu_ui32_to_f64); + break; + case UI32_TO_EXTF80: + /* not implemented */ + break; + case UI32_TO_F128: + /* not implemented */ + break; + case UI64_TO_F16: + test_a_ui64_z_f16(slow_ui64_to_f16, qemu_ui64_to_f16); + break; + case UI64_TO_F32: + test_a_ui64_z_f32(slow_ui64_to_f32, qemu_ui64_to_f32); + break; + case UI64_TO_F64: + test_a_ui64_z_f64(slow_ui64_to_f64, qemu_ui64_to_f64); + break; + case UI64_TO_EXTF80: + /* not implemented */ + break; + case UI64_TO_F128: + test_a_ui64_z_f128(slow_ui64_to_f128M, qemu_ui64_to_f128M); + break; + case I32_TO_F16: + test_a_i32_z_f16(slow_i32_to_f16, qemu_i32_to_f16); + break; + case I32_TO_F32: + test_a_i32_z_f32(slow_i32_to_f32, qemu_i32_to_f32); + break; + case I32_TO_F64: + test_a_i32_z_f64(slow_i32_to_f64, qemu_i32_to_f64); + break; + case I32_TO_EXTF80: + test_a_i32_z_extF80(slow_i32_to_extF80M, qemu_i32_to_extF80M); + break; + case I32_TO_F128: + test_a_i32_z_f128(slow_i32_to_f128M, qemu_i32_to_f128M); + break; + case I64_TO_F16: + test_a_i64_z_f16(slow_i64_to_f16, qemu_i64_to_f16); + break; + case I64_TO_F32: + test_a_i64_z_f32(slow_i64_to_f32, qemu_i64_to_f32); + break; + case I64_TO_F64: + test_a_i64_z_f64(slow_i64_to_f64, qemu_i64_to_f64); + break; + case I64_TO_EXTF80: + test_a_i64_z_extF80(slow_i64_to_extF80M, qemu_i64_to_extF80M); + break; + case I64_TO_F128: + test_a_i64_z_f128(slow_i64_to_f128M, qemu_i64_to_f128M); + break; + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + case F16_TO_UI32: + test_a_f16_z_ui32_rx( + slow_f16_to_ui32, qemu_f16_to_ui32, roundingMode, exact); + break; + case F16_TO_UI64: + test_a_f16_z_ui64_rx( + slow_f16_to_ui64, qemu_f16_to_ui64, roundingMode, exact); + break; + case F16_TO_I32: + test_a_f16_z_i32_rx( + slow_f16_to_i32, qemu_f16_to_i32, roundingMode, exact); + break; + case F16_TO_I64: + test_a_f16_z_i64_rx( + slow_f16_to_i64, qemu_f16_to_i64, roundingMode, exact); + break; + case F16_TO_UI32_R_MINMAG: + /* not implemented */ + break; + case F16_TO_UI64_R_MINMAG: + /* not implemented */ + break; + case F16_TO_I32_R_MINMAG: + /* not implemented */ + break; + case F16_TO_I64_R_MINMAG: + /* not implemented */ + break; + case F16_TO_F32: + test_a_f16_z_f32(slow_f16_to_f32, qemu_f16_to_f32); + break; + case F16_TO_F64: + test_a_f16_z_f64(slow_f16_to_f64, qemu_f16_to_f64); + break; + case F16_TO_EXTF80: + /* not implemented */ + break; + case F16_TO_F128: + /* not implemented */ + break; + case F16_ROUNDTOINT: + test_az_f16_rx( + slow_f16_roundToInt, qemu_f16_roundToInt, roundingMode, exact); + break; + case F16_ADD: + trueFunction_abz_f16 = slow_f16_add; + subjFunction_abz_f16 = qemu_f16_add; + goto test_abz_f16; + case F16_SUB: + trueFunction_abz_f16 = slow_f16_sub; + subjFunction_abz_f16 = qemu_f16_sub; + goto test_abz_f16; + case F16_MUL: + trueFunction_abz_f16 = slow_f16_mul; + subjFunction_abz_f16 = qemu_f16_mul; + goto test_abz_f16; + case F16_DIV: + trueFunction_abz_f16 = slow_f16_div; + subjFunction_abz_f16 = qemu_f16_div; + goto test_abz_f16; + case F16_REM: + /* not implemented */ + break; + test_abz_f16: + test_abz_f16(trueFunction_abz_f16, subjFunction_abz_f16); + break; + case F16_MULADD: + test_abcz_f16(slow_f16_mulAdd, qemu_f16_mulAdd); + break; + case F16_SQRT: + test_az_f16(slow_f16_sqrt, qemu_f16_sqrt); + break; + case F16_EQ: + trueFunction_ab_f16_z_bool = slow_f16_eq; + subjFunction_ab_f16_z_bool = qemu_f16_eq; + goto test_ab_f16_z_bool; + case F16_LE: + trueFunction_ab_f16_z_bool = slow_f16_le; + subjFunction_ab_f16_z_bool = qemu_f16_le; + goto test_ab_f16_z_bool; + case F16_LT: + trueFunction_ab_f16_z_bool = slow_f16_lt; + subjFunction_ab_f16_z_bool = qemu_f16_lt; + goto test_ab_f16_z_bool; + case F16_EQ_SIGNALING: + trueFunction_ab_f16_z_bool = slow_f16_eq_signaling; + subjFunction_ab_f16_z_bool = qemu_f16_eq_signaling; + goto test_ab_f16_z_bool; + case F16_LE_QUIET: + trueFunction_ab_f16_z_bool = slow_f16_le_quiet; + subjFunction_ab_f16_z_bool = qemu_f16_le_quiet; + goto test_ab_f16_z_bool; + case F16_LT_QUIET: + trueFunction_ab_f16_z_bool = slow_f16_lt_quiet; + subjFunction_ab_f16_z_bool = qemu_f16_lt_quiet; + test_ab_f16_z_bool: + test_ab_f16_z_bool( + trueFunction_ab_f16_z_bool, subjFunction_ab_f16_z_bool); + break; + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + case F32_TO_UI32: + test_a_f32_z_ui32_rx( + slow_f32_to_ui32, qemu_f32_to_ui32, roundingMode, exact); + break; + case F32_TO_UI64: + test_a_f32_z_ui64_rx( + slow_f32_to_ui64, qemu_f32_to_ui64, roundingMode, exact); + break; + case F32_TO_I32: + test_a_f32_z_i32_rx( + slow_f32_to_i32, qemu_f32_to_i32, roundingMode, exact); + break; + case F32_TO_I64: + test_a_f32_z_i64_rx( + slow_f32_to_i64, qemu_f32_to_i64, roundingMode, exact); + break; + case F32_TO_UI32_R_MINMAG: + /* not implemented */ + break; + case F32_TO_UI64_R_MINMAG: + /* not implemented */ + break; + case F32_TO_I32_R_MINMAG: + /* not implemented */ + break; + case F32_TO_I64_R_MINMAG: + /* not implemented */ + break; + case F32_TO_F16: + test_a_f32_z_f16(slow_f32_to_f16, qemu_f32_to_f16); + break; + case F32_TO_F64: + test_a_f32_z_f64(slow_f32_to_f64, qemu_f32_to_f64); + break; + case F32_TO_EXTF80: + test_a_f32_z_extF80(slow_f32_to_extF80M, qemu_f32_to_extF80M); + break; + case F32_TO_F128: + test_a_f32_z_f128(slow_f32_to_f128M, qemu_f32_to_f128M); + break; + case F32_ROUNDTOINT: + test_az_f32_rx( + slow_f32_roundToInt, qemu_f32_roundToInt, roundingMode, exact); + break; + case F32_ADD: + trueFunction_abz_f32 = slow_f32_add; + subjFunction_abz_f32 = qemu_f32_add; + goto test_abz_f32; + case F32_SUB: + trueFunction_abz_f32 = slow_f32_sub; + subjFunction_abz_f32 = qemu_f32_sub; + goto test_abz_f32; + case F32_MUL: + trueFunction_abz_f32 = slow_f32_mul; + subjFunction_abz_f32 = qemu_f32_mul; + goto test_abz_f32; + case F32_DIV: + trueFunction_abz_f32 = slow_f32_div; + subjFunction_abz_f32 = qemu_f32_div; + goto test_abz_f32; + case F32_REM: + trueFunction_abz_f32 = slow_f32_rem; + subjFunction_abz_f32 = qemu_f32_rem; + test_abz_f32: + test_abz_f32(trueFunction_abz_f32, subjFunction_abz_f32); + break; + case F32_MULADD: + test_abcz_f32(slow_f32_mulAdd, qemu_f32_mulAdd); + break; + case F32_SQRT: + test_az_f32(slow_f32_sqrt, qemu_f32_sqrt); + break; + case F32_EQ: + trueFunction_ab_f32_z_bool = slow_f32_eq; + subjFunction_ab_f32_z_bool = qemu_f32_eq; + goto test_ab_f32_z_bool; + case F32_LE: + trueFunction_ab_f32_z_bool = slow_f32_le; + subjFunction_ab_f32_z_bool = qemu_f32_le; + goto test_ab_f32_z_bool; + case F32_LT: + trueFunction_ab_f32_z_bool = slow_f32_lt; + subjFunction_ab_f32_z_bool = qemu_f32_lt; + goto test_ab_f32_z_bool; + case F32_EQ_SIGNALING: + trueFunction_ab_f32_z_bool = slow_f32_eq_signaling; + subjFunction_ab_f32_z_bool = qemu_f32_eq_signaling; + goto test_ab_f32_z_bool; + case F32_LE_QUIET: + trueFunction_ab_f32_z_bool = slow_f32_le_quiet; + subjFunction_ab_f32_z_bool = qemu_f32_le_quiet; + goto test_ab_f32_z_bool; + case F32_LT_QUIET: + trueFunction_ab_f32_z_bool = slow_f32_lt_quiet; + subjFunction_ab_f32_z_bool = qemu_f32_lt_quiet; + test_ab_f32_z_bool: + test_ab_f32_z_bool( + trueFunction_ab_f32_z_bool, subjFunction_ab_f32_z_bool); + break; + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + case F64_TO_UI32: + test_a_f64_z_ui32_rx( + slow_f64_to_ui32, qemu_f64_to_ui32, roundingMode, exact); + break; + case F64_TO_UI64: + test_a_f64_z_ui64_rx( + slow_f64_to_ui64, qemu_f64_to_ui64, roundingMode, exact); + break; + case F64_TO_I32: + test_a_f64_z_i32_rx( + slow_f64_to_i32, qemu_f64_to_i32, roundingMode, exact); + break; + case F64_TO_I64: + test_a_f64_z_i64_rx( + slow_f64_to_i64, qemu_f64_to_i64, roundingMode, exact); + break; + case F64_TO_UI32_R_MINMAG: + /* not implemented */ + break; + case F64_TO_UI64_R_MINMAG: + /* not implemented */ + break; + case F64_TO_I32_R_MINMAG: + /* not implemented */ + break; + case F64_TO_I64_R_MINMAG: + /* not implemented */ + break; + case F64_TO_F16: + test_a_f64_z_f16(slow_f64_to_f16, qemu_f64_to_f16); + break; + case F64_TO_F32: + test_a_f64_z_f32(slow_f64_to_f32, qemu_f64_to_f32); + break; + case F64_TO_EXTF80: + test_a_f64_z_extF80(slow_f64_to_extF80M, qemu_f64_to_extF80M); + break; + case F64_TO_F128: + test_a_f64_z_f128(slow_f64_to_f128M, qemu_f64_to_f128M); + break; + case F64_ROUNDTOINT: + test_az_f64_rx( + slow_f64_roundToInt, qemu_f64_roundToInt, roundingMode, exact); + break; + case F64_ADD: + trueFunction_abz_f64 = slow_f64_add; + subjFunction_abz_f64 = qemu_f64_add; + goto test_abz_f64; + case F64_SUB: + trueFunction_abz_f64 = slow_f64_sub; + subjFunction_abz_f64 = qemu_f64_sub; + goto test_abz_f64; + case F64_MUL: + trueFunction_abz_f64 = slow_f64_mul; + subjFunction_abz_f64 = qemu_f64_mul; + goto test_abz_f64; + case F64_DIV: + trueFunction_abz_f64 = slow_f64_div; + subjFunction_abz_f64 = qemu_f64_div; + goto test_abz_f64; + case F64_REM: + trueFunction_abz_f64 = slow_f64_rem; + subjFunction_abz_f64 = qemu_f64_rem; + test_abz_f64: + test_abz_f64(trueFunction_abz_f64, subjFunction_abz_f64); + break; + case F64_MULADD: + test_abcz_f64(slow_f64_mulAdd, qemu_f64_mulAdd); + break; + case F64_SQRT: + test_az_f64(slow_f64_sqrt, qemu_f64_sqrt); + break; + case F64_EQ: + trueFunction_ab_f64_z_bool = slow_f64_eq; + subjFunction_ab_f64_z_bool = qemu_f64_eq; + goto test_ab_f64_z_bool; + case F64_LE: + trueFunction_ab_f64_z_bool = slow_f64_le; + subjFunction_ab_f64_z_bool = qemu_f64_le; + goto test_ab_f64_z_bool; + case F64_LT: + trueFunction_ab_f64_z_bool = slow_f64_lt; + subjFunction_ab_f64_z_bool = qemu_f64_lt; + goto test_ab_f64_z_bool; + case F64_EQ_SIGNALING: + trueFunction_ab_f64_z_bool = slow_f64_eq_signaling; + subjFunction_ab_f64_z_bool = qemu_f64_eq_signaling; + goto test_ab_f64_z_bool; + case F64_LE_QUIET: + trueFunction_ab_f64_z_bool = slow_f64_le_quiet; + subjFunction_ab_f64_z_bool = qemu_f64_le_quiet; + goto test_ab_f64_z_bool; + case F64_LT_QUIET: + trueFunction_ab_f64_z_bool = slow_f64_lt_quiet; + subjFunction_ab_f64_z_bool = qemu_f64_lt_quiet; + test_ab_f64_z_bool: + test_ab_f64_z_bool( + trueFunction_ab_f64_z_bool, subjFunction_ab_f64_z_bool); + break; + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + case EXTF80_TO_UI32: + /* not implemented */ + break; + case EXTF80_TO_UI64: + /* not implemented */ + break; + case EXTF80_TO_I32: + test_a_extF80_z_i32_rx( + slow_extF80M_to_i32, qemu_extF80M_to_i32, roundingMode, exact); + break; + case EXTF80_TO_I64: + test_a_extF80_z_i64_rx( + slow_extF80M_to_i64, qemu_extF80M_to_i64, roundingMode, exact); + break; + case EXTF80_TO_UI32_R_MINMAG: + /* not implemented */ + break; + case EXTF80_TO_UI64_R_MINMAG: + /* not implemented */ + break; + case EXTF80_TO_I32_R_MINMAG: + /* not implemented */ + break; + case EXTF80_TO_I64_R_MINMAG: + /* not implemented */ + break; + case EXTF80_TO_F16: + /* not implemented */ + break; + case EXTF80_TO_F32: + test_a_extF80_z_f32(slow_extF80M_to_f32, qemu_extF80M_to_f32); + break; + case EXTF80_TO_F64: + test_a_extF80_z_f64(slow_extF80M_to_f64, qemu_extF80M_to_f64); + break; + case EXTF80_TO_F128: + test_a_extF80_z_f128(slow_extF80M_to_f128M, qemu_extF80M_to_f128M); + break; + case EXTF80_ROUNDTOINT: + test_az_extF80_rx( + slow_extF80M_roundToInt, qemu_extF80M_roundToInt, roundingMode, exact); + break; + case EXTF80_ADD: + trueFunction_abz_extF80M = slow_extF80M_add; + subjFunction_abz_extF80M = qemu_extF80M_add; + goto test_abz_extF80; + case EXTF80_SUB: + trueFunction_abz_extF80M = slow_extF80M_sub; + subjFunction_abz_extF80M = qemu_extF80M_sub; + goto test_abz_extF80; + case EXTF80_MUL: + trueFunction_abz_extF80M = slow_extF80M_mul; + subjFunction_abz_extF80M = qemu_extF80M_mul; + goto test_abz_extF80; + case EXTF80_DIV: + trueFunction_abz_extF80M = slow_extF80M_div; + subjFunction_abz_extF80M = qemu_extF80M_div; + goto test_abz_extF80; + case EXTF80_REM: + trueFunction_abz_extF80M = slow_extF80M_rem; + subjFunction_abz_extF80M = qemu_extF80M_rem; + test_abz_extF80: + test_abz_extF80(trueFunction_abz_extF80M, subjFunction_abz_extF80M); + break; + case EXTF80_SQRT: + test_az_extF80(slow_extF80M_sqrt, qemu_extF80M_sqrt); + break; + case EXTF80_EQ: + trueFunction_ab_extF80M_z_bool = slow_extF80M_eq; + subjFunction_ab_extF80M_z_bool = qemu_extF80M_eq; + goto test_ab_extF80_z_bool; + case EXTF80_LE: + trueFunction_ab_extF80M_z_bool = slow_extF80M_le; + subjFunction_ab_extF80M_z_bool = qemu_extF80M_le; + goto test_ab_extF80_z_bool; + case EXTF80_LT: + trueFunction_ab_extF80M_z_bool = slow_extF80M_lt; + subjFunction_ab_extF80M_z_bool = qemu_extF80M_lt; + goto test_ab_extF80_z_bool; + case EXTF80_EQ_SIGNALING: + trueFunction_ab_extF80M_z_bool = slow_extF80M_eq_signaling; + subjFunction_ab_extF80M_z_bool = qemu_extF80M_eq_signaling; + goto test_ab_extF80_z_bool; + case EXTF80_LE_QUIET: + trueFunction_ab_extF80M_z_bool = slow_extF80M_le_quiet; + subjFunction_ab_extF80M_z_bool = qemu_extF80M_le_quiet; + goto test_ab_extF80_z_bool; + case EXTF80_LT_QUIET: + trueFunction_ab_extF80M_z_bool = slow_extF80M_lt_quiet; + subjFunction_ab_extF80M_z_bool = qemu_extF80M_lt_quiet; + test_ab_extF80_z_bool: + test_ab_extF80_z_bool( + trueFunction_ab_extF80M_z_bool, subjFunction_ab_extF80M_z_bool); + break; + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + case F128_TO_UI32: + /* not implemented */ + break; + case F128_TO_UI64: + test_a_f128_z_ui64_rx( + slow_f128M_to_ui64, qemu_f128M_to_ui64, roundingMode, exact); + break; + case F128_TO_I32: + test_a_f128_z_i32_rx( + slow_f128M_to_i32, qemu_f128M_to_i32, roundingMode, exact); + break; + case F128_TO_I64: + test_a_f128_z_i64_rx( + slow_f128M_to_i64, qemu_f128M_to_i64, roundingMode, exact); + break; + case F128_TO_UI32_R_MINMAG: + /* not implemented */ + break; + case F128_TO_UI64_R_MINMAG: + /* not implemented */ + break; + case F128_TO_I32_R_MINMAG: + /* not implemented */ + break; + case F128_TO_I64_R_MINMAG: + /* not implemented */ + break; + case F128_TO_F16: + /* not implemented */ + break; + case F128_TO_F32: + test_a_f128_z_f32(slow_f128M_to_f32, qemu_f128M_to_f32); + break; + case F128_TO_F64: + test_a_f128_z_f64(slow_f128M_to_f64, qemu_f128M_to_f64); + break; + case F128_TO_EXTF80: + test_a_f128_z_extF80(slow_f128M_to_extF80M, qemu_f128M_to_extF80M); + break; + case F128_ROUNDTOINT: + test_az_f128_rx( + slow_f128M_roundToInt, qemu_f128M_roundToInt, roundingMode, exact); + break; + case F128_ADD: + trueFunction_abz_f128M = slow_f128M_add; + subjFunction_abz_f128M = qemu_f128M_add; + goto test_abz_f128; + case F128_SUB: + trueFunction_abz_f128M = slow_f128M_sub; + subjFunction_abz_f128M = qemu_f128M_sub; + goto test_abz_f128; + case F128_MUL: + trueFunction_abz_f128M = slow_f128M_mul; + subjFunction_abz_f128M = qemu_f128M_mul; + goto test_abz_f128; + case F128_DIV: + trueFunction_abz_f128M = slow_f128M_div; + subjFunction_abz_f128M = qemu_f128M_div; + goto test_abz_f128; + case F128_REM: + trueFunction_abz_f128M = slow_f128M_rem; + subjFunction_abz_f128M = qemu_f128M_rem; + test_abz_f128: + test_abz_f128(trueFunction_abz_f128M, subjFunction_abz_f128M); + break; + case F128_MULADD: + /* not implemented */ + break; + case F128_SQRT: + test_az_f128(slow_f128M_sqrt, qemu_f128M_sqrt); + break; + case F128_EQ: + trueFunction_ab_f128M_z_bool = slow_f128M_eq; + subjFunction_ab_f128M_z_bool = qemu_f128M_eq; + goto test_ab_f128_z_bool; + case F128_LE: + trueFunction_ab_f128M_z_bool = slow_f128M_le; + subjFunction_ab_f128M_z_bool = qemu_f128M_le; + goto test_ab_f128_z_bool; + case F128_LT: + trueFunction_ab_f128M_z_bool = slow_f128M_lt; + subjFunction_ab_f128M_z_bool = qemu_f128M_lt; + goto test_ab_f128_z_bool; + case F128_EQ_SIGNALING: + trueFunction_ab_f128M_z_bool = slow_f128M_eq_signaling; + subjFunction_ab_f128M_z_bool = qemu_f128M_eq_signaling; + goto test_ab_f128_z_bool; + case F128_LE_QUIET: + trueFunction_ab_f128M_z_bool = slow_f128M_le_quiet; + subjFunction_ab_f128M_z_bool = qemu_f128M_le_quiet; + goto test_ab_f128_z_bool; + case F128_LT_QUIET: + trueFunction_ab_f128M_z_bool = slow_f128M_lt_quiet; + subjFunction_ab_f128M_z_bool = qemu_f128M_lt_quiet; + test_ab_f128_z_bool: + test_ab_f128_z_bool( + trueFunction_ab_f128M_z_bool, subjFunction_ab_f128M_z_bool); + break; + } + if ((verCases_errorStop && verCases_anyErrors) || verCases_stop) { + verCases_exitWithStatus(); + } +} + +static void +testFunction(int functionCode, uint_fast8_t roundingPrecisionIn, + int roundingCodeIn, int tininessCodeIn, int exactCodeIn) +{ + int functionAttribs; + uint_fast8_t roundingPrecision; + int roundingCode; + uint_fast8_t roundingMode = { 0 }; + int exactCode; + bool exact; + int tininessCode; + uint_fast8_t tininessMode; + + functionAttribs = functionInfos[functionCode].attribs; + verCases_functionNamePtr = functionInfos[functionCode].namePtr; + roundingPrecision = 32; + for (;;) { + if (functionAttribs & FUNC_EFF_ROUNDINGPRECISION) { + if (roundingPrecisionIn) { + roundingPrecision = roundingPrecisionIn; + } + } else { + roundingPrecision = 0; + } + verCases_roundingPrecision = roundingPrecision; + if (roundingPrecision) { + slow_extF80_roundingPrecision = roundingPrecision; + qsf.floatx80_rounding_precision = roundingPrecision; + } + /* XXX: not testing ROUND_ODD */ + for (roundingCode = 1; roundingCode < NUM_ROUNDINGMODES - 1; + ++roundingCode) { + if ( + functionAttribs + & (FUNC_ARG_ROUNDINGMODE | FUNC_EFF_ROUNDINGMODE) + ) { + if (roundingCodeIn) { + roundingCode = roundingCodeIn; + } + } else { + roundingCode = 0; + } + verCases_roundingCode = roundingCode; + if (roundingCode) { + roundingMode = roundingModes[roundingCode]; + if (functionAttribs & FUNC_EFF_ROUNDINGMODE) { + slowfloat_roundingMode = roundingMode; + qsf.float_rounding_mode = + softfloat_rounding_to_qemu(roundingMode); + } + } + /* + * XXX not testing EXACT_FALSE + * for (exactCode = EXACT_FALSE; exactCode <= EXACT_TRUE; + * ++exactCode) + */ + exactCode = EXACT_TRUE; + { + if (functionAttribs & FUNC_ARG_EXACT) { + if (exactCodeIn) { + exactCode = exactCodeIn; + } + } else { + exactCode = 0; + } + exact = (exactCode == EXACT_TRUE); + verCases_usesExact = (exactCode != 0); + verCases_exact = exact; + for ( + tininessCode = 1; + tininessCode < NUM_TININESSMODES; + ++tininessCode + ) { + if ( + (functionAttribs & FUNC_EFF_TININESSMODE) + || ((functionAttribs + & FUNC_EFF_TININESSMODE_REDUCEDPREC) + && roundingPrecision + && (roundingPrecision < 80)) + ) { + if (tininessCodeIn) { + tininessCode = tininessCodeIn; + } + } else { + tininessCode = 0; + } + verCases_tininessCode = tininessCode; + if (tininessCode) { + tininessMode = tininessModes[tininessCode]; + slowfloat_detectTininess = tininessMode; + qsf.float_detect_tininess = + softfloat_tininess_to_qemu(tininessMode); + } + testFunctionInstance(functionCode, roundingMode, exact); + if (tininessCodeIn || !tininessCode) { + break; + } + } + if (exactCodeIn || !exactCode) { + break; + } + } + if (roundingCodeIn || !roundingCode) { + break; + } + } + if (roundingPrecisionIn || !roundingPrecision) { + break; + } + if (roundingPrecision == 80) { + break; + } else if (roundingPrecision == 64) { + roundingPrecision = 80; + } else if (roundingPrecision == 32) { + roundingPrecision = 64; + } + } + +} + +int main(int argc, char *argv[]) +{ + bool haveFunctionArg; + int functionCode, numOperands; + uint_fast8_t roundingPrecision; + int roundingCode, tininessCode, exactCode; + const char *argPtr; + unsigned long ui; + long i; + int functionMatchAttrib; + struct sigaction sigact; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + fail_programName = (char *)"testsoftfloat"; + if (argc <= 1) { + goto writeHelpMessage; + } + genCases_setLevel(1); + verCases_maxErrorCount = 20; + testLoops_trueFlagsPtr = &slowfloat_exceptionFlags; + testLoops_subjFlagsFunction = qemu_softfloat_clearExceptionFlags; + haveFunctionArg = false; + functionCode = 0; + numOperands = 0; + roundingPrecision = 0; + roundingCode = 0; + tininessCode = 0; + exactCode = 0; + for (;;) { + --argc; + if (!argc) { + break; + } + argPtr = *++argv; + if (!argPtr) { + break; + } + if (argPtr[0] == '-') { + ++argPtr; + } + if ( + !strcmp(argPtr, "help") || !strcmp(argPtr, "-help") + || !strcmp(argPtr, "h") + ) { + writeHelpMessage: + fputs( + "testsoftfloat [