target-alpha: Raise IOV from CVTTQ

Floating-point overflow is a different bit from integer overflow.

Reported-by: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Richard Henderson 2014-06-28 12:57:03 -07:00
parent f6b6b7b8a7
commit c24a8a0b6d
3 changed files with 13 additions and 30 deletions

View File

@ -427,12 +427,9 @@ uint64_t helper_cvtqs(CPUAlphaState *env, uint64_t a)
/* Implement float64 to uint64 conversion without saturation -- we must
supply the truncated result. This behaviour is used by the compiler
to get unsigned conversion for free with the same instruction.
to get unsigned conversion for free with the same instruction. */
The VI flag is set when overflow or inexact exceptions should be raised. */
static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a,
int roundmode, int VI)
static uint64_t do_cvttq(CPUAlphaState *env, uint64_t a, int roundmode)
{
uint64_t frac, ret = 0;
uint32_t exp, sign, exc = 0;
@ -447,7 +444,7 @@ static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a,
goto do_underflow;
}
} else if (exp == 0x7ff) {
exc = (frac ? FPCR_INV : VI ? FPCR_OVF : 0);
exc = (frac ? FPCR_INV : FPCR_IOV | FPCR_INE);
} else {
/* Restore implicit bit. */
frac |= 0x10000000000000ull;
@ -456,10 +453,11 @@ static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a,
if (shift >= 0) {
/* In this case the number is so large that we must shift
the fraction left. There is no rounding to do. */
exc = FPCR_IOV | FPCR_INE;
if (shift < 63) {
ret = frac << shift;
if (VI && (ret >> shift) != frac) {
exc = FPCR_OVF;
if ((ret >> shift) == frac) {
exc = 0;
}
}
} else {
@ -482,7 +480,7 @@ static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a,
}
if (round) {
exc = (VI ? FPCR_INE : 0);
exc = FPCR_INE;
switch (roundmode) {
case float_round_nearest_even:
if (round == (1ull << 63)) {
@ -514,17 +512,12 @@ static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a,
uint64_t helper_cvttq(CPUAlphaState *env, uint64_t a)
{
return inline_cvttq(env, a, FP_STATUS.float_rounding_mode, 1);
return do_cvttq(env, a, FP_STATUS.float_rounding_mode);
}
uint64_t helper_cvttq_c(CPUAlphaState *env, uint64_t a)
{
return inline_cvttq(env, a, float_round_to_zero, 0);
}
uint64_t helper_cvttq_svic(CPUAlphaState *env, uint64_t a)
{
return inline_cvttq(env, a, float_round_to_zero, 1);
return do_cvttq(env, a, float_round_to_zero);
}
uint64_t helper_cvtqt(CPUAlphaState *env, uint64_t a)

View File

@ -83,7 +83,6 @@ DEF_HELPER_FLAGS_2(cvtqg, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_2(cvttq, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_2(cvttq_c, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_2(cvttq_svic, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_2(setroundmode, TCG_CALL_NO_RWG, void, env, i32)
DEF_HELPER_FLAGS_2(setflushzero, TCG_CALL_NO_RWG, void, env, i32)

View File

@ -760,23 +760,14 @@ static void gen_cvttq(DisasContext *ctx, int rb, int rc, int fn11)
vb = gen_ieee_input(ctx, rb, fn11, 0);
vc = dest_fpr(ctx, rc);
/* Almost all integer conversions use cropped rounding, and most
also do not have integer overflow enabled. Special case that. */
switch (fn11) {
case QUAL_RM_C:
/* Almost all integer conversions use cropped rounding;
special case that. */
if ((fn11 & QUAL_RM_MASK) == QUAL_RM_C) {
gen_helper_cvttq_c(vc, cpu_env, vb);
break;
case QUAL_V | QUAL_RM_C:
case QUAL_S | QUAL_V | QUAL_RM_C:
case QUAL_S | QUAL_V | QUAL_I | QUAL_RM_C:
gen_helper_cvttq_svic(vc, cpu_env, vb);
break;
default:
} else {
gen_qual_roundmode(ctx, fn11);
gen_helper_cvttq(vc, cpu_env, vb);
break;
}
gen_fp_exc_raise(rc, fn11);
}