[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 14/36] target/i386: Return 'indefinite integer value'
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PULL 14/36] target/i386: Return 'indefinite integer value' for invalid SSE fp->int conversions |
Date: |
Tue, 20 Aug 2019 08:59:33 +0200 |
From: Peter Maydell <address@hidden>
The x86 architecture requires that all conversions from floating
point to integer which raise the 'invalid' exception (infinities of
both signs, NaN, and all values which don't fit in the destination
integer) return what the x86 spec calls the "indefinite integer
value", which is 0x8000_0000 for 32-bits or 0x8000_0000_0000_0000 for
64-bits. The softfloat functions return the more usual behaviour of
positive overflows returning the maximum value that fits in the
destination integer format and negative overflows returning the
minimum value that fits.
Wrap the softfloat functions in x86-specific versions which
detect the 'invalid' condition and return the indefinite integer.
Note that we don't use these wrappers for the 3DNow! pf2id and pf2iw
instructions, which do return the minimum value that fits in
an int32 if the input float is a large negative number.
Fixes: https://bugs.launchpad.net/qemu/+bug/1815423
Signed-off-by: Peter Maydell <address@hidden>
Message-Id: <address@hidden>
Reviewed-by: Richard Henderson <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
---
target/i386/ops_sse.h | 88 +++++++++++++++++++++++++++++++++++----------------
1 file changed, 60 insertions(+), 28 deletions(-)
diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index ed05989..ec1ec74 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -710,102 +710,134 @@ void helper_cvtsq2sd(CPUX86State *env, ZMMReg *d,
uint64_t val)
#endif
/* float to integer */
+
+/*
+ * x86 mandates that we return the indefinite integer value for the result
+ * of any float-to-integer conversion that raises the 'invalid' exception.
+ * Wrap the softfloat functions to get this behaviour.
+ */
+#define WRAP_FLOATCONV(RETTYPE, FN, FLOATTYPE, INDEFVALUE) \
+ static inline RETTYPE x86_##FN(FLOATTYPE a, float_status *s) \
+ { \
+ int oldflags, newflags; \
+ RETTYPE r; \
+ \
+ oldflags = get_float_exception_flags(s); \
+ set_float_exception_flags(0, s); \
+ r = FN(a, s); \
+ newflags = get_float_exception_flags(s); \
+ if (newflags & float_flag_invalid) { \
+ r = INDEFVALUE; \
+ } \
+ set_float_exception_flags(newflags | oldflags, s); \
+ return r; \
+ }
+
+WRAP_FLOATCONV(int32_t, float32_to_int32, float32, INT32_MIN)
+WRAP_FLOATCONV(int32_t, float32_to_int32_round_to_zero, float32, INT32_MIN)
+WRAP_FLOATCONV(int32_t, float64_to_int32, float64, INT32_MIN)
+WRAP_FLOATCONV(int32_t, float64_to_int32_round_to_zero, float64, INT32_MIN)
+WRAP_FLOATCONV(int64_t, float32_to_int64, float32, INT64_MIN)
+WRAP_FLOATCONV(int64_t, float32_to_int64_round_to_zero, float32, INT64_MIN)
+WRAP_FLOATCONV(int64_t, float64_to_int64, float64, INT64_MIN)
+WRAP_FLOATCONV(int64_t, float64_to_int64_round_to_zero, float64, INT64_MIN)
+
void helper_cvtps2dq(CPUX86State *env, ZMMReg *d, ZMMReg *s)
{
- d->ZMM_L(0) = float32_to_int32(s->ZMM_S(0), &env->sse_status);
- d->ZMM_L(1) = float32_to_int32(s->ZMM_S(1), &env->sse_status);
- d->ZMM_L(2) = float32_to_int32(s->ZMM_S(2), &env->sse_status);
- d->ZMM_L(3) = float32_to_int32(s->ZMM_S(3), &env->sse_status);
+ d->ZMM_L(0) = x86_float32_to_int32(s->ZMM_S(0), &env->sse_status);
+ d->ZMM_L(1) = x86_float32_to_int32(s->ZMM_S(1), &env->sse_status);
+ d->ZMM_L(2) = x86_float32_to_int32(s->ZMM_S(2), &env->sse_status);
+ d->ZMM_L(3) = x86_float32_to_int32(s->ZMM_S(3), &env->sse_status);
}
void helper_cvtpd2dq(CPUX86State *env, ZMMReg *d, ZMMReg *s)
{
- d->ZMM_L(0) = float64_to_int32(s->ZMM_D(0), &env->sse_status);
- d->ZMM_L(1) = float64_to_int32(s->ZMM_D(1), &env->sse_status);
+ d->ZMM_L(0) = x86_float64_to_int32(s->ZMM_D(0), &env->sse_status);
+ d->ZMM_L(1) = x86_float64_to_int32(s->ZMM_D(1), &env->sse_status);
d->ZMM_Q(1) = 0;
}
void helper_cvtps2pi(CPUX86State *env, MMXReg *d, ZMMReg *s)
{
- d->MMX_L(0) = float32_to_int32(s->ZMM_S(0), &env->sse_status);
- d->MMX_L(1) = float32_to_int32(s->ZMM_S(1), &env->sse_status);
+ d->MMX_L(0) = x86_float32_to_int32(s->ZMM_S(0), &env->sse_status);
+ d->MMX_L(1) = x86_float32_to_int32(s->ZMM_S(1), &env->sse_status);
}
void helper_cvtpd2pi(CPUX86State *env, MMXReg *d, ZMMReg *s)
{
- d->MMX_L(0) = float64_to_int32(s->ZMM_D(0), &env->sse_status);
- d->MMX_L(1) = float64_to_int32(s->ZMM_D(1), &env->sse_status);
+ d->MMX_L(0) = x86_float64_to_int32(s->ZMM_D(0), &env->sse_status);
+ d->MMX_L(1) = x86_float64_to_int32(s->ZMM_D(1), &env->sse_status);
}
int32_t helper_cvtss2si(CPUX86State *env, ZMMReg *s)
{
- return float32_to_int32(s->ZMM_S(0), &env->sse_status);
+ return x86_float32_to_int32(s->ZMM_S(0), &env->sse_status);
}
int32_t helper_cvtsd2si(CPUX86State *env, ZMMReg *s)
{
- return float64_to_int32(s->ZMM_D(0), &env->sse_status);
+ return x86_float64_to_int32(s->ZMM_D(0), &env->sse_status);
}
#ifdef TARGET_X86_64
int64_t helper_cvtss2sq(CPUX86State *env, ZMMReg *s)
{
- return float32_to_int64(s->ZMM_S(0), &env->sse_status);
+ return x86_float32_to_int64(s->ZMM_S(0), &env->sse_status);
}
int64_t helper_cvtsd2sq(CPUX86State *env, ZMMReg *s)
{
- return float64_to_int64(s->ZMM_D(0), &env->sse_status);
+ return x86_float64_to_int64(s->ZMM_D(0), &env->sse_status);
}
#endif
/* float to integer truncated */
void helper_cvttps2dq(CPUX86State *env, ZMMReg *d, ZMMReg *s)
{
- d->ZMM_L(0) = float32_to_int32_round_to_zero(s->ZMM_S(0),
&env->sse_status);
- d->ZMM_L(1) = float32_to_int32_round_to_zero(s->ZMM_S(1),
&env->sse_status);
- d->ZMM_L(2) = float32_to_int32_round_to_zero(s->ZMM_S(2),
&env->sse_status);
- d->ZMM_L(3) = float32_to_int32_round_to_zero(s->ZMM_S(3),
&env->sse_status);
+ d->ZMM_L(0) = x86_float32_to_int32_round_to_zero(s->ZMM_S(0),
&env->sse_status);
+ d->ZMM_L(1) = x86_float32_to_int32_round_to_zero(s->ZMM_S(1),
&env->sse_status);
+ d->ZMM_L(2) = x86_float32_to_int32_round_to_zero(s->ZMM_S(2),
&env->sse_status);
+ d->ZMM_L(3) = x86_float32_to_int32_round_to_zero(s->ZMM_S(3),
&env->sse_status);
}
void helper_cvttpd2dq(CPUX86State *env, ZMMReg *d, ZMMReg *s)
{
- d->ZMM_L(0) = float64_to_int32_round_to_zero(s->ZMM_D(0),
&env->sse_status);
- d->ZMM_L(1) = float64_to_int32_round_to_zero(s->ZMM_D(1),
&env->sse_status);
+ d->ZMM_L(0) = x86_float64_to_int32_round_to_zero(s->ZMM_D(0),
&env->sse_status);
+ d->ZMM_L(1) = x86_float64_to_int32_round_to_zero(s->ZMM_D(1),
&env->sse_status);
d->ZMM_Q(1) = 0;
}
void helper_cvttps2pi(CPUX86State *env, MMXReg *d, ZMMReg *s)
{
- d->MMX_L(0) = float32_to_int32_round_to_zero(s->ZMM_S(0),
&env->sse_status);
- d->MMX_L(1) = float32_to_int32_round_to_zero(s->ZMM_S(1),
&env->sse_status);
+ d->MMX_L(0) = x86_float32_to_int32_round_to_zero(s->ZMM_S(0),
&env->sse_status);
+ d->MMX_L(1) = x86_float32_to_int32_round_to_zero(s->ZMM_S(1),
&env->sse_status);
}
void helper_cvttpd2pi(CPUX86State *env, MMXReg *d, ZMMReg *s)
{
- d->MMX_L(0) = float64_to_int32_round_to_zero(s->ZMM_D(0),
&env->sse_status);
- d->MMX_L(1) = float64_to_int32_round_to_zero(s->ZMM_D(1),
&env->sse_status);
+ d->MMX_L(0) = x86_float64_to_int32_round_to_zero(s->ZMM_D(0),
&env->sse_status);
+ d->MMX_L(1) = x86_float64_to_int32_round_to_zero(s->ZMM_D(1),
&env->sse_status);
}
int32_t helper_cvttss2si(CPUX86State *env, ZMMReg *s)
{
- return float32_to_int32_round_to_zero(s->ZMM_S(0), &env->sse_status);
+ return x86_float32_to_int32_round_to_zero(s->ZMM_S(0), &env->sse_status);
}
int32_t helper_cvttsd2si(CPUX86State *env, ZMMReg *s)
{
- return float64_to_int32_round_to_zero(s->ZMM_D(0), &env->sse_status);
+ return x86_float64_to_int32_round_to_zero(s->ZMM_D(0), &env->sse_status);
}
#ifdef TARGET_X86_64
int64_t helper_cvttss2sq(CPUX86State *env, ZMMReg *s)
{
- return float32_to_int64_round_to_zero(s->ZMM_S(0), &env->sse_status);
+ return x86_float32_to_int64_round_to_zero(s->ZMM_S(0), &env->sse_status);
}
int64_t helper_cvttsd2sq(CPUX86State *env, ZMMReg *s)
{
- return float64_to_int64_round_to_zero(s->ZMM_D(0), &env->sse_status);
+ return x86_float64_to_int64_round_to_zero(s->ZMM_D(0), &env->sse_status);
}
#endif
--
1.8.3.1
- [Qemu-devel] [PULL 13/36] i386/kvm: initialize struct at full before ioctl call, (continued)
- [Qemu-devel] [PULL 13/36] i386/kvm: initialize struct at full before ioctl call, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 21/36] replay: add missing fix for internal function, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 24/36] replay: fix replay shutdown, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 22/36] replay: document development rules, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 30/36] cpus-common: assert BQL nesting within cpu-exclusive sections, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 31/36] kvm: vmxcap: Enhance with latest features, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 16/36] mc146818rtc: Remove reset notifiers, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 15/36] memory: fix race between TCG and accesses to dirty bitmap, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 17/36] timer: Remove reset notifiers, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 12/36] tests: Fix uninitialized byte in test_visitor_in_fuzz, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 14/36] target/i386: Return 'indefinite integer value' for invalid SSE fp->int conversions,
Paolo Bonzini <=
- [Qemu-devel] [PULL 19/36] timer: last, remove last bits of last, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 20/36] kconfig: do not select VMMOUSE, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 18/36] replay: Remove host_clock_last, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 25/36] replay: refine replay-time module, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 29/36] cpus-common: nuke finish_safe_work, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 27/36] icount: clean up cpu_can_io at the entry to the block, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 36/36] x86: Intel AVX512_BF16 feature enabling, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 28/36] icount: remove unnecessary gen_io_end calls, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 26/36] replay: rename step-related variables and functions, Paolo Bonzini, 2019/08/20
- [Qemu-devel] [PULL 32/36] HACKING: Document 'struct' keyword usage, Paolo Bonzini, 2019/08/20