From 446cfb0d3487a630ab52efe35977dec24a6db384 Mon Sep 17 00:00:00 2001 From: "Emilio G. Cota" Date: Fri, 21 Dec 2018 14:51:59 -0500 Subject: [PATCH 01/11] fp-bench: fix update_random_ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The second test in the branches is wrong; fix while converting to a switch statement, which is easier to get right. Signed-off-by: Emilio G. Cota Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Alex Bennée --- tests/fp/fp-bench.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c index f5bc5edebf..546bac9c9c 100644 --- a/tests/fp/fp-bench.c +++ b/tests/fp/fp-bench.c @@ -143,15 +143,20 @@ static void update_random_ops(int n_ops, enum precision prec) for (i = 0; i < n_ops; i++) { uint64_t r = random_ops[i]; - if (prec == PREC_SINGLE || PREC_FLOAT32) { + switch (prec) { + case PREC_SINGLE: + case PREC_FLOAT32: do { r = xorshift64star(r); } while (!float32_is_normal(r)); - } else if (prec == PREC_DOUBLE || PREC_FLOAT64) { + break; + case PREC_DOUBLE: + case PREC_FLOAT64: do { r = xorshift64star(r); } while (!float64_is_normal(r)); - } else { + break; + default: g_assert_not_reached(); } random_ops[i] = r; From 392a8adc41ccf182ad0ecf83ab44137a556e6e87 Mon Sep 17 00:00:00 2001 From: "Emilio G. Cota" Date: Fri, 21 Dec 2018 14:52:00 -0500 Subject: [PATCH 02/11] fp-bench: remove wrong exponent raise in fill_random MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At this point random_ops[] only contains normals, so there's no need to do anything to them. In fact, raising the exponent here can make the output !normal, which is precisely what the comment says we want to avoid. Signed-off-by: Emilio G. Cota Reviewed-by: Richard Henderson Signed-off-by: Alex Bennée --- tests/fp/fp-bench.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c index 546bac9c9c..4ba5e1d2d4 100644 --- a/tests/fp/fp-bench.c +++ b/tests/fp/fp-bench.c @@ -176,8 +176,6 @@ static void fill_random(union fp *ops, int n_ops, enum precision prec, if (no_neg && float32_is_neg(ops[i].f32)) { ops[i].f32 = float32_chs(ops[i].f32); } - /* raise the exponent to limit the frequency of denormal results */ - ops[i].f32 |= 0x40000000; break; case PREC_DOUBLE: case PREC_FLOAT64: @@ -185,8 +183,6 @@ static void fill_random(union fp *ops, int n_ops, enum precision prec, if (no_neg && float64_is_neg(ops[i].f64)) { ops[i].f64 = float64_chs(ops[i].f64); } - /* raise the exponent to limit the frequency of denormal results */ - ops[i].f64 |= LIT64(0x4000000000000000); break; default: g_assert_not_reached(); From 8b148365eeb650e3a6b024ba367c6a356942b173 Mon Sep 17 00:00:00 2001 From: "Emilio G. Cota" Date: Thu, 17 Jan 2019 13:17:48 -0500 Subject: [PATCH 03/11] berkeley-testfloat-3: pull changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fail: constify fail_programName Signed-off-by: Emilio G. Cota Signed-off-by: Alex Bennée --- tests/fp/berkeley-testfloat-3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fp/berkeley-testfloat-3 b/tests/fp/berkeley-testfloat-3 index ca9fa2ba05..5a59dcec19 160000 --- a/tests/fp/berkeley-testfloat-3 +++ b/tests/fp/berkeley-testfloat-3 @@ -1 +1 @@ -Subproject commit ca9fa2ba05625ba929958f163b01747e07dd39cc +Subproject commit 5a59dcec19327396a011a17fd924aed4fec416b3 From 2cb0dac60acfb447f436327a96e505fa8e2eb326 Mon Sep 17 00:00:00 2001 From: "Emilio G. Cota" Date: Thu, 17 Jan 2019 13:18:46 -0500 Subject: [PATCH 04/11] tests/fp/Makefile: do not use gcc-only -W flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The build now completes in both gcc and clang. Signed-off-by: Emilio G. Cota Signed-off-by: Alex Bennée --- tests/fp/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/fp/Makefile b/tests/fp/Makefile index 5019dcdca0..5a35e7c210 100644 --- a/tests/fp/Makefile +++ b/tests/fp/Makefile @@ -65,8 +65,7 @@ QEMU_CFLAGS += $(TF_OPTS) TF_CFLAGS := TF_CFLAGS += -Wno-strict-prototypes TF_CFLAGS += -Wno-unknown-pragmas -TF_CFLAGS += -Wno-discarded-qualifiers -TF_CFLAGS += -Wno-maybe-uninitialized +TF_CFLAGS += -Wno-uninitialized TF_CFLAGS += -Wno-missing-prototypes TF_CFLAGS += -Wno-return-type TF_CFLAGS += -Wno-unused-function From 710fbcd2b2b11ae1f8f82ae48cadcaefd4cf48b2 Mon Sep 17 00:00:00 2001 From: "Emilio G. Cota" Date: Thu, 17 Jan 2019 13:22:12 -0500 Subject: [PATCH 05/11] fp-test: fix signature of slow_clear_flags and qemu_clear_flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To match the type in testfloat. Signed-off-by: Emilio G. Cota Signed-off-by: Alex Bennée --- tests/fp/fp-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c index fca576309c..2a35ef601d 100644 --- a/tests/fp/fp-test.c +++ b/tests/fp/fp-test.c @@ -789,7 +789,7 @@ static int set_init_flags(const char *flags) return 0; } -static uint8_t slow_clear_flags(void) +static uint_fast8_t slow_clear_flags(void) { uint8_t prev = slowfloat_exceptionFlags; @@ -797,7 +797,7 @@ static uint8_t slow_clear_flags(void) return prev; } -static uint8_t qemu_clear_flags(void) +static uint_fast8_t qemu_clear_flags(void) { uint8_t prev = qemu_flags_to_sf(qsf.float_exception_flags); From b343eb462bcf825d60a29269054d54aff95b1722 Mon Sep 17 00:00:00 2001 From: "Emilio G. Cota" Date: Tue, 22 Jan 2019 15:10:42 -0500 Subject: [PATCH 06/11] tests/fp/platform.h: include config-host.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We get HOST_WORDS_BIGENDIAN from config-host.h, but the include is missing. Fix it. This fixes `make check-softfloat' on big endian hosts. Reported-by: Peter Maydell Signed-off-by: Emilio G. Cota Signed-off-by: Alex Bennée --- tests/fp/platform.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fp/platform.h b/tests/fp/platform.h index f8c423dde3..c20ba70baa 100644 --- a/tests/fp/platform.h +++ b/tests/fp/platform.h @@ -29,6 +29,7 @@ * (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 From f6b3b108a808fe07f8a45f82bc88196f668cf627 Mon Sep 17 00:00:00 2001 From: "Emilio G. Cota" Date: Tue, 25 Dec 2018 02:03:05 -0500 Subject: [PATCH 07/11] softfloat: enforce softfloat if the host's FMA is broken MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The added branch to the FMA ops is marked as unlikely and therefore its impact on performance (measured with fp-bench) is within noise range when measured on an Intel(R) Xeon(R) Gold 6142 CPU @ 2.60GHz. Reported-by: Laurent Desnogues Signed-off-by: Emilio G. Cota Reviewed-by: Richard Henderson Signed-off-by: Alex Bennée --- fpu/softfloat.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 59eac97d10..9132d7a0b0 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1542,6 +1542,8 @@ soft_f64_muladd(float64 a, float64 b, float64 c, int flags, return float64_round_pack_canonical(pr, status); } +static bool force_soft_fma; + float32 QEMU_FLATTEN float32_muladd(float32 xa, float32 xb, float32 xc, int flags, float_status *s) { @@ -1562,6 +1564,11 @@ float32_muladd(float32 xa, float32 xb, float32 xc, int flags, float_status *s) if (unlikely(!f32_is_zon3(ua, ub, uc))) { goto soft; } + + if (unlikely(force_soft_fma)) { + goto soft; + } + /* * When (a || b) == 0, there's no need to check for under/over flow, * since we know the addend is (normal || 0) and the product is 0. @@ -1623,6 +1630,11 @@ float64_muladd(float64 xa, float64 xb, float64 xc, int flags, float_status *s) if (unlikely(!f64_is_zon3(ua, ub, uc))) { goto soft; } + + if (unlikely(force_soft_fma)) { + goto soft; + } + /* * When (a || b) == 0, there's no need to check for under/over flow, * since we know the addend is (normal || 0) and the product is 0. @@ -7974,3 +7986,24 @@ float128 float128_scalbn(float128 a, int n, float_status *status) , status); } + +static void __attribute__((constructor)) softfloat_init(void) +{ + union_float64 ua, ub, uc, ur; + + if (QEMU_NO_HARDFLOAT) { + return; + } + /* + * Test that the host's FMA is not obviously broken. For example, + * glibc < 2.23 can perform an incorrect FMA on certain hosts; see + * https://sourceware.org/bugzilla/show_bug.cgi?id=13304 + */ + ua.s = 0x0020000000000001ULL; + ub.s = 0x3ca0000000000000ULL; + uc.s = 0x0020000000000000ULL; + ur.h = fma(ua.h, ub.h, uc.h); + if (ur.s != 0x0020000000000001ULL) { + force_soft_fma = true; + } +} From 2c00542c70b9cbd6da510c97cd3d46adcf9e3efc Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 14 Jan 2019 13:12:35 +0100 Subject: [PATCH 08/11] include/fpu/softfloat: Fix compilation with Clang on s390x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clang v7.0.1 does not like the __int128 variable type for inline assembly on s390x: In file included from fpu/softfloat.c:97: include/fpu/softfloat-macros.h:647:9: error: inline asm error: This value type register class is not natively supported! asm("dlgr %0, %1" : "+r"(n) : "r"(d)); ^ Disable this code part there now when compiling with Clang, so that the generic code gets used instead. Signed-off-by: Thomas Huth Reviewed-by: Richard Henderson Acked-by: Cornelia Huck Signed-off-by: Alex Bennée --- include/fpu/softfloat-macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fpu/softfloat-macros.h b/include/fpu/softfloat-macros.h index b1d772e6d4..bd5b6418e3 100644 --- a/include/fpu/softfloat-macros.h +++ b/include/fpu/softfloat-macros.h @@ -641,7 +641,7 @@ static inline uint64_t udiv_qrnnd(uint64_t *r, uint64_t n1, uint64_t q; asm("divq %4" : "=a"(q), "=d"(*r) : "0"(n0), "1"(n1), "rm"(d)); return q; -#elif defined(__s390x__) +#elif defined(__s390x__) && !defined(__clang__) /* Need to use a TImode type to get an even register pair for DLGR. */ unsigned __int128 n = (unsigned __int128)n1 << 64 | n0; asm("dlgr %0, %1" : "+r"(n) : "r"(d)); From 2cade3d7e542a0be8e2c6c8b1d3b499a9b14cb27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 7 Jan 2019 17:22:19 +0000 Subject: [PATCH 09/11] tests/Makefile: add floating point tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wire up test/fp-test into the main testing Makefile. Currently we skip some of the extF80 and f128 related tests. Once we re-factor and fix these tests the plumbing should get simpler. Signed-off-by: Alex Bennée --- tests/Makefile.include | 120 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/tests/Makefile.include b/tests/Makefile.include index 4eea38ae99..ec5428b798 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -880,6 +880,126 @@ check-report-unit.tap: $(check-unit-y) check-report.tap: $(patsubst %,check-report-qtest-%.tap, $(QTEST_TARGETS)) check-report-unit.tap $(call quiet-command,./scripts/tap-merge.py $^ > $@,"GEN","$@") +# FPU Emulation tests (aka softfloat) +# +# As we still have some places that need fixing the rules are a little +# more complex than they need to be and have to override some of the +# generic Makefile expansions. Once we are cleanly passing all +# the tests we can simplify the make syntax. + +FP_TEST_BIN=$(BUILD_DIR)/tests/fp/fp-test + +# the build dir is created by configure +.PHONY: $(FP_TEST_BIN) +$(FP_TEST_BIN): + $(call quiet-command, \ + $(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" $(notdir $@), \ + "BUILD", "$(notdir $@)") + +# The full test suite can take a bit of time, default to a quick run +ifeq ($(SPEED), quick) +FP_TL=-l 1 +else +FP_TL=-l 2 -r all +endif + +# $1 = tests, $2 = description +test-softfloat = $(call quiet-command, \ + cd $(BUILD_DIR)/tests/fp && \ + ./fp-test -s $(FP_TL) $1 > $2.out 2>&1 || \ + (cat $2.out && exit 1;), \ + "FLOAT TEST", $2) + +# Conversion Routines: +# FIXME: i32_to_extF80 (broken), i64_to_extF80 (broken) +# ui32_to_f128 (not implemented), f128_to_ui32 (not implemented) +# extF80_roundToInt (broken) +# +check-softfloat-conv: $(FP_TEST_BIN) + $(call test-softfloat, \ + i32_to_f16 i64_to_f16 \ + i32_to_f32 i64_to_f32 \ + i32_to_f64 i64_to_f64 \ + i32_to_f128 i64_to_f128, int-to-float) + $(call test-softfloat, \ + ui32_to_f16 ui64_to_f16 \ + ui32_to_f32 ui64_to_f32 \ + ui32_to_f64 ui64_to_f64 \ + ui64_to_f128, uint-to-float) + $(call test-softfloat, \ + f16_to_i32 f16_to_i32_r_minMag \ + f32_to_i32 f32_to_i32_r_minMag \ + f64_to_i32 f64_to_i32_r_minMag \ + extF80_to_i32 extF80_to_i32_r_minMag \ + f128_to_i32 f128_to_i32_r_minMag \ + f16_to_i64 f16_to_i64_r_minMag \ + f32_to_i64 f32_to_i64_r_minMag \ + f64_to_i64 f64_to_i64_r_minMag \ + extF80_to_i64 extF80_to_i64_r_minMag \ + f128_to_i64 f128_to_i64_r_minMag, \ + float-to-int) + $(call test-softfloat, \ + f16_to_ui32 f16_to_ui32_r_minMag \ + f32_to_ui32 f32_to_ui32_r_minMag \ + f64_to_ui32 f64_to_ui32_r_minMag \ + f16_to_ui64 f16_to_ui64_r_minMag \ + f32_to_ui64 f32_to_ui64_r_minMag \ + f64_to_ui64 f64_to_ui64_r_minMag, \ + float-to-uint) + $(call test-softfloat, \ + f16_roundToInt f32_roundToInt \ + f64_roundToInt f128_roundToInt, \ + round-to-integer) + +# Generic rule for all float operations +# +# Some patterns are overidden due to broken or missing tests. +# Hopefully these can be removed over time. + +check-softfloat-%: $(FP_TEST_BIN) + $(call test-softfloat, f16_$* f32_$* f64_$* extF80_$* f128_$*, $*) + +# Float Compare routines +SF_COMPARE_OPS=eq eq_signaling le le_quiet lt_quiet +SF_COMPARE_RULES=$(patsubst %,check-softfloat-%, $(SF_COMPARE_OPS)) + +# FIXME: extF80_le_quiet (broken) +check-softfloat-le_quiet: $(FP_TEST_BIN) + $(call test-softfloat, \ + f16_le_quiet f32_le_quiet f64_le_quiet \ + f128_le_quiet, \ + le_quiet) + +# FIXME: extF80_lt_quiet (broken) +check-softfloat-lt_quiet: $(FP_TEST_BIN) + $(call test-softfloat, \ + f16_lt_quiet f32_lt_quiet f64_lt_quiet \ + f128_lt_quiet, \ + lt_quiet) + +.PHONY: check-softfloat-compare +check-softfloat-compare: $(SF_COMPARE_RULES) + +# Math Operations + +# FIXME: extF80_mulAdd (missing) +check-softfloat-mulAdd: $(FP_TEST_BIN) + $(call test-softfloat, \ + f16_mulAdd f32_mulAdd f64_mulAdd f128_mulAdd, \ + mulAdd) + +# FIXME: extF80_rem (broken) +check-softfloat-rem: $(FP_TEST_BIN) + $(call test-softfloat, \ + f16_rem f32_rem f64_rem f128_rem, \ + rem) + +SF_MATH_OPS=add sub mul mulAdd div rem sqrt +SF_MATH_RULES=$(patsubst %,check-softfloat-%, $(SF_MATH_OPS)) + +.PHONY: check-softfloat-ops +check-softfloat-ops: $(SF_MATH_RULES) + # Per guest TCG tests LINUX_USER_TARGETS=$(filter %-linux-user,$(TARGET_DIRS)) From 1627a36ead992596612ae4079146a182af82c3af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 8 Jan 2019 11:51:53 +0000 Subject: [PATCH 10/11] scripts/archive-source: include softfloat tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need these if we want to run unit/softfloat tests in our docker containers. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson --- scripts/archive-source.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/archive-source.sh b/scripts/archive-source.sh index 62bd22578b..6eed2a29bd 100755 --- a/scripts/archive-source.sh +++ b/scripts/archive-source.sh @@ -26,7 +26,7 @@ vroot_dir="${tar_file}.vroot" # independent of what the developer currently has initialized # in their checkout, because the build environment is completely # different to the host OS. -submodules="dtc ui/keycodemapdb" +submodules="dtc ui/keycodemapdb tests/fp/berkeley-softfloat-3 tests/fp/berkeley-testfloat-3" trap "status=$?; rm -rf \"$list_file\" \"$vroot_dir\"; exit \$status" 0 1 2 3 15 From 7617010250822677348af2bd98f048be10e7f334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 7 Jan 2019 17:25:44 +0000 Subject: [PATCH 11/11] tests/Makefile: add check-softfloat rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a rule to run all of our softfloat tests. It is included as a pre-requisite to check-tcg and check-unit as well. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson Reviewed-by: Emilio G. Cota --- tests/Makefile.include | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tests/Makefile.include b/tests/Makefile.include index ec5428b798..f5e6eb5152 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -12,6 +12,7 @@ check-help: @echo " $(MAKE) check-qapi-schema Run QAPI schema tests" @echo " $(MAKE) check-block Run block tests" @echo " $(MAKE) check-tcg Run TCG tests" + @echo " $(MAKE) check-softfloat Run FPU emulation tests" @echo " $(MAKE) check-acceptance Run all acceptance (functional) tests" @echo @echo " $(MAKE) check-report.html Generates an HTML test report" @@ -1000,6 +1001,18 @@ SF_MATH_RULES=$(patsubst %,check-softfloat-%, $(SF_MATH_OPS)) .PHONY: check-softfloat-ops check-softfloat-ops: $(SF_MATH_RULES) +# Finally a generic rule to test all of softfoat. If TCG isnt't +# enabled we define a null operation which skips the tests. + +.PHONY: check-softfloat +ifeq ($(CONFIG_TCG),y) +check-softfloat: check-softfloat-conv check-softfloat-compare check-softfloat-ops +else +check-softfloat: + $(call quiet-command, /bin/true, "FLOAT TEST", \ + "SKIPPED for non-TCG builds") +endif + # Per guest TCG tests LINUX_USER_TARGETS=$(filter %-linux-user,$(TARGET_DIRS)) @@ -1032,7 +1045,7 @@ clean-tcg-tests-%: build-tcg: $(BUILD_TCG_TARGET_RULES) .PHONY: check-tcg -check-tcg: $(RUN_TCG_TARGET_RULES) +check-tcg: check-softfloat $(RUN_TCG_TARGET_RULES) .PHONY: clean-tcg clean-tcg: $(CLEAN_TCG_TARGET_RULES) @@ -1113,7 +1126,7 @@ check-acceptance: check-venv $(TESTS_RESULTS_DIR) check-qapi-schema: $(patsubst %,check-%, $(check-qapi-schema-y)) check-tests/qapi-schema/doc-good.texi check-qtest: $(patsubst %,check-qtest-%, $(QTEST_TARGETS)) check-block: $(patsubst %,check-%, $(check-block-y)) -check: check-qapi-schema check-unit check-qtest check-decodetree +check: check-qapi-schema check-unit check-softfloat check-qtest check-decodetree check-clean: rm -rf $(check-unit-y) tests/*.o $(QEMU_IOTESTS_HELPERS-y) rm -rf $(sort $(foreach target,$(SYSEMU_TARGET_LIST), $(check-qtest-$(target)-y)) $(check-qtest-generic-y))