From 18c53e1e73197a24f9f4b66b1276eb9868db5bf0 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Wed, 13 May 2020 23:51:09 +0000 Subject: [PATCH] target/i386: fix fbstp handling of negative zero The fbstp implementation stores +0 when the rounded result should be -0 because it compares an integer value with 0 to determine the sign. Fix this by checking the sign bit of the operand instead. Signed-off-by: Joseph Myers Message-Id: Signed-off-by: Paolo Bonzini --- target/i386/fpu_helper.c | 5 ++++- tests/tcg/i386/test-i386-fbstp.c | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/tcg/i386/test-i386-fbstp.c diff --git a/target/i386/fpu_helper.c b/target/i386/fpu_helper.c index 185493db8e..f0a57099ca 100644 --- a/target/i386/fpu_helper.c +++ b/target/i386/fpu_helper.c @@ -726,11 +726,14 @@ void helper_fbst_ST0(CPUX86State *env, target_ulong ptr) int v; target_ulong mem_ref, mem_end; int64_t val; + CPU_LDoubleU temp; + + temp.d = ST0; val = floatx80_to_int64(ST0, &env->fp_status); mem_ref = ptr; mem_end = mem_ref + 9; - if (val < 0) { + if (SIGND(temp)) { cpu_stb_data_ra(env, mem_end, 0x80, GETPC()); val = -val; } else { diff --git a/tests/tcg/i386/test-i386-fbstp.c b/tests/tcg/i386/test-i386-fbstp.c new file mode 100644 index 0000000000..d368949188 --- /dev/null +++ b/tests/tcg/i386/test-i386-fbstp.c @@ -0,0 +1,25 @@ +/* Test fbstp instruction. */ + +#include +#include + +int main(void) +{ + int ret = 0; + unsigned char out[10]; + memset(out, 0xfe, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-0.0L) : "st"); + out[9] &= 0x80; + if (memcmp(out, "\0\0\0\0\0\0\0\0\0\x80", sizeof out) != 0) { + printf("FAIL: fbstp -0\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-0.1L) : "st"); + out[9] &= 0x80; + if (memcmp(out, "\0\0\0\0\0\0\0\0\0\x80", sizeof out) != 0) { + printf("FAIL: fbstp -0.1\n"); + ret = 1; + } + return ret; +} -- 2.11.4.GIT