Commit 17218d1fd9b33a94028bdca3c4e9481f05e0a318
1 parent
f23c346e
target-ppc: fadd/fsub: correctly propagate NaN
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6052 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
8 additions
and
18 deletions
target-ppc/op_helper.c
| @@ -563,17 +563,7 @@ static always_inline int isden (float64 d) | @@ -563,17 +563,7 @@ static always_inline int isden (float64 d) | ||
| 563 | return ((u.ll >> 52) & 0x7FF) == 0; | 563 | return ((u.ll >> 52) & 0x7FF) == 0; |
| 564 | } | 564 | } |
| 565 | 565 | ||
| 566 | - | ||
| 567 | #ifdef CONFIG_SOFTFLOAT | 566 | #ifdef CONFIG_SOFTFLOAT |
| 568 | -static always_inline int isfinite (float64 d) | ||
| 569 | -{ | ||
| 570 | - CPU_DoubleU u; | ||
| 571 | - | ||
| 572 | - u.d = d; | ||
| 573 | - | ||
| 574 | - return (((u.ll >> 52) & 0x7FF) != 0x7FF); | ||
| 575 | -} | ||
| 576 | - | ||
| 577 | static always_inline int isnormal (float64 d) | 567 | static always_inline int isnormal (float64 d) |
| 578 | { | 568 | { |
| 579 | CPU_DoubleU u; | 569 | CPU_DoubleU u; |
| @@ -1028,12 +1018,12 @@ uint64_t helper_fadd (uint64_t arg1, uint64_t arg2) | @@ -1028,12 +1018,12 @@ uint64_t helper_fadd (uint64_t arg1, uint64_t arg2) | ||
| 1028 | float64_is_signaling_nan(farg2.d))) { | 1018 | float64_is_signaling_nan(farg2.d))) { |
| 1029 | /* sNaN addition */ | 1019 | /* sNaN addition */ |
| 1030 | farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); | 1020 | farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); |
| 1031 | - } else if (likely(isfinite(farg1.d) || isfinite(farg2.d) || | ||
| 1032 | - float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) { | ||
| 1033 | - farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status); | ||
| 1034 | - } else { | 1021 | + } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) && |
| 1022 | + float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) { | ||
| 1035 | /* Magnitude subtraction of infinities */ | 1023 | /* Magnitude subtraction of infinities */ |
| 1036 | farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI); | 1024 | farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI); |
| 1025 | + } else { | ||
| 1026 | + farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status); | ||
| 1037 | } | 1027 | } |
| 1038 | #else | 1028 | #else |
| 1039 | farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status); | 1029 | farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status); |
| @@ -1054,12 +1044,12 @@ uint64_t helper_fsub (uint64_t arg1, uint64_t arg2) | @@ -1054,12 +1044,12 @@ uint64_t helper_fsub (uint64_t arg1, uint64_t arg2) | ||
| 1054 | float64_is_signaling_nan(farg2.d))) { | 1044 | float64_is_signaling_nan(farg2.d))) { |
| 1055 | /* sNaN subtraction */ | 1045 | /* sNaN subtraction */ |
| 1056 | farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); | 1046 | farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); |
| 1057 | - } else if (likely(isfinite(farg1.d) || isfinite(farg2.d) || | ||
| 1058 | - float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) { | ||
| 1059 | - farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status); | ||
| 1060 | - } else { | 1047 | + } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) && |
| 1048 | + float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) { | ||
| 1061 | /* Magnitude subtraction of infinities */ | 1049 | /* Magnitude subtraction of infinities */ |
| 1062 | farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI); | 1050 | farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI); |
| 1051 | + } else { | ||
| 1052 | + farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status); | ||
| 1063 | } | 1053 | } |
| 1064 | } | 1054 | } |
| 1065 | #else | 1055 | #else |