From 225f6f288929b24b3989ad6e033c7ba8a5364661 Mon Sep 17 00:00:00 2001 From: liangjs <761232680@qq.com> Date: Mon, 21 Sep 2020 10:39:00 +0800 Subject: [PATCH] Return 'indefinite integer value' for invalid SSE fp->int conversions (#1306) Merge from qemu commit 1e8a98b53867f61da9ca09f411288e2085d323c4. https://github.com/qemu/qemu/commit/1e8a98b53867f61da9ca09f411288e2085d323c4 --- qemu/target-i386/ops_sse.h | 88 ++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 28 deletions(-) diff --git a/qemu/target-i386/ops_sse.h b/qemu/target-i386/ops_sse.h index 45e5ce65..8a8cda91 100644 --- a/qemu/target-i386/ops_sse.h +++ b/qemu/target-i386/ops_sse.h @@ -710,102 +710,134 @@ void helper_cvtsq2sd(CPUX86State *env, XMMReg *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, XMMReg *d, XMMReg *s) { - d->XMM_L(0) = float32_to_int32(s->XMM_S(0), &env->sse_status); - d->XMM_L(1) = float32_to_int32(s->XMM_S(1), &env->sse_status); - d->XMM_L(2) = float32_to_int32(s->XMM_S(2), &env->sse_status); - d->XMM_L(3) = float32_to_int32(s->XMM_S(3), &env->sse_status); + d->XMM_L(0) = x86_float32_to_int32(s->XMM_S(0), &env->sse_status); + d->XMM_L(1) = x86_float32_to_int32(s->XMM_S(1), &env->sse_status); + d->XMM_L(2) = x86_float32_to_int32(s->XMM_S(2), &env->sse_status); + d->XMM_L(3) = x86_float32_to_int32(s->XMM_S(3), &env->sse_status); } void helper_cvtpd2dq(CPUX86State *env, XMMReg *d, XMMReg *s) { - d->XMM_L(0) = float64_to_int32(s->XMM_D(0), &env->sse_status); - d->XMM_L(1) = float64_to_int32(s->XMM_D(1), &env->sse_status); + d->XMM_L(0) = x86_float64_to_int32(s->XMM_D(0), &env->sse_status); + d->XMM_L(1) = x86_float64_to_int32(s->XMM_D(1), &env->sse_status); d->XMM_Q(1) = 0; } void helper_cvtps2pi(CPUX86State *env, MMXReg *d, XMMReg *s) { - d->MMX_L(0) = float32_to_int32(s->XMM_S(0), &env->sse_status); - d->MMX_L(1) = float32_to_int32(s->XMM_S(1), &env->sse_status); + d->MMX_L(0) = x86_float32_to_int32(s->XMM_S(0), &env->sse_status); + d->MMX_L(1) = x86_float32_to_int32(s->XMM_S(1), &env->sse_status); } void helper_cvtpd2pi(CPUX86State *env, MMXReg *d, XMMReg *s) { - d->MMX_L(0) = float64_to_int32(s->XMM_D(0), &env->sse_status); - d->MMX_L(1) = float64_to_int32(s->XMM_D(1), &env->sse_status); + d->MMX_L(0) = x86_float64_to_int32(s->XMM_D(0), &env->sse_status); + d->MMX_L(1) = x86_float64_to_int32(s->XMM_D(1), &env->sse_status); } int32_t helper_cvtss2si(CPUX86State *env, XMMReg *s) { - return float32_to_int32(s->XMM_S(0), &env->sse_status); + return x86_float32_to_int32(s->XMM_S(0), &env->sse_status); } int32_t helper_cvtsd2si(CPUX86State *env, XMMReg *s) { - return float64_to_int32(s->XMM_D(0), &env->sse_status); + return x86_float64_to_int32(s->XMM_D(0), &env->sse_status); } #ifdef TARGET_X86_64 int64_t helper_cvtss2sq(CPUX86State *env, XMMReg *s) { - return float32_to_int64(s->XMM_S(0), &env->sse_status); + return x86_float32_to_int64(s->XMM_S(0), &env->sse_status); } int64_t helper_cvtsd2sq(CPUX86State *env, XMMReg *s) { - return float64_to_int64(s->XMM_D(0), &env->sse_status); + return x86_float64_to_int64(s->XMM_D(0), &env->sse_status); } #endif /* float to integer truncated */ void helper_cvttps2dq(CPUX86State *env, XMMReg *d, XMMReg *s) { - d->XMM_L(0) = float32_to_int32_round_to_zero(s->XMM_S(0), &env->sse_status); - d->XMM_L(1) = float32_to_int32_round_to_zero(s->XMM_S(1), &env->sse_status); - d->XMM_L(2) = float32_to_int32_round_to_zero(s->XMM_S(2), &env->sse_status); - d->XMM_L(3) = float32_to_int32_round_to_zero(s->XMM_S(3), &env->sse_status); + d->XMM_L(0) = x86_float32_to_int32_round_to_zero(s->XMM_S(0), &env->sse_status); + d->XMM_L(1) = x86_float32_to_int32_round_to_zero(s->XMM_S(1), &env->sse_status); + d->XMM_L(2) = x86_float32_to_int32_round_to_zero(s->XMM_S(2), &env->sse_status); + d->XMM_L(3) = x86_float32_to_int32_round_to_zero(s->XMM_S(3), &env->sse_status); } void helper_cvttpd2dq(CPUX86State *env, XMMReg *d, XMMReg *s) { - d->XMM_L(0) = float64_to_int32_round_to_zero(s->XMM_D(0), &env->sse_status); - d->XMM_L(1) = float64_to_int32_round_to_zero(s->XMM_D(1), &env->sse_status); + d->XMM_L(0) = x86_float64_to_int32_round_to_zero(s->XMM_D(0), &env->sse_status); + d->XMM_L(1) = x86_float64_to_int32_round_to_zero(s->XMM_D(1), &env->sse_status); d->XMM_Q(1) = 0; } void helper_cvttps2pi(CPUX86State *env, MMXReg *d, XMMReg *s) { - d->MMX_L(0) = float32_to_int32_round_to_zero(s->XMM_S(0), &env->sse_status); - d->MMX_L(1) = float32_to_int32_round_to_zero(s->XMM_S(1), &env->sse_status); + d->MMX_L(0) = x86_float32_to_int32_round_to_zero(s->XMM_S(0), &env->sse_status); + d->MMX_L(1) = x86_float32_to_int32_round_to_zero(s->XMM_S(1), &env->sse_status); } void helper_cvttpd2pi(CPUX86State *env, MMXReg *d, XMMReg *s) { - d->MMX_L(0) = float64_to_int32_round_to_zero(s->XMM_D(0), &env->sse_status); - d->MMX_L(1) = float64_to_int32_round_to_zero(s->XMM_D(1), &env->sse_status); + d->MMX_L(0) = x86_float64_to_int32_round_to_zero(s->XMM_D(0), &env->sse_status); + d->MMX_L(1) = x86_float64_to_int32_round_to_zero(s->XMM_D(1), &env->sse_status); } int32_t helper_cvttss2si(CPUX86State *env, XMMReg *s) { - return float32_to_int32_round_to_zero(s->XMM_S(0), &env->sse_status); + return x86_float32_to_int32_round_to_zero(s->XMM_S(0), &env->sse_status); } int32_t helper_cvttsd2si(CPUX86State *env, XMMReg *s) { - return float64_to_int32_round_to_zero(s->XMM_D(0), &env->sse_status); + return x86_float64_to_int32_round_to_zero(s->XMM_D(0), &env->sse_status); } #ifdef TARGET_X86_64 int64_t helper_cvttss2sq(CPUX86State *env, XMMReg *s) { - return float32_to_int64_round_to_zero(s->XMM_S(0), &env->sse_status); + return x86_float32_to_int64_round_to_zero(s->XMM_S(0), &env->sse_status); } int64_t helper_cvttsd2sq(CPUX86State *env, XMMReg *s) { - return float64_to_int64_round_to_zero(s->XMM_D(0), &env->sse_status); + return x86_float64_to_int64_round_to_zero(s->XMM_D(0), &env->sse_status); } #endif