target-ppc: fix fcmp{o,u} instructions

The instructions are specified to update the condition register even if
an error is to be signaled because of NaN input.

Signed-off-by: Nathan Froyd <froydnj@codesourcery.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6034 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
aurel32 2008-12-14 19:34:09 +00:00
parent b12363e1b7
commit 9a819377d8
3 changed files with 53 additions and 43 deletions

View file

@ -1620,32 +1620,7 @@ uint64_t helper_fsel (uint64_t arg1, uint64_t arg2, uint64_t arg3)
return arg3;
}
uint32_t helper_fcmpu (uint64_t arg1, uint64_t arg2)
{
CPU_DoubleU farg1, farg2;
uint32_t ret = 0;
farg1.ll = arg1;
farg2.ll = arg2;
if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d))) {
/* sNaN comparison */
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
} else {
if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
ret = 0x08UL;
} else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
ret = 0x04UL;
} else {
ret = 0x02UL;
}
}
env->fpscr &= ~(0x0F << FPSCR_FPRF);
env->fpscr |= ret << FPSCR_FPRF;
return ret;
}
uint32_t helper_fcmpo (uint64_t arg1, uint64_t arg2)
void helper_fcmpu (uint64_t arg1, uint64_t arg2, uint32_t crfD)
{
CPU_DoubleU farg1, farg2;
uint32_t ret = 0;
@ -1654,6 +1629,48 @@ uint32_t helper_fcmpo (uint64_t arg1, uint64_t arg2)
if (unlikely(float64_is_nan(farg1.d) ||
float64_is_nan(farg2.d))) {
ret = 0x01UL;
} else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
ret = 0x08UL;
} else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
ret = 0x04UL;
} else {
ret = 0x02UL;
}
env->fpscr &= ~(0x0F << FPSCR_FPRF);
env->fpscr |= ret << FPSCR_FPRF;
env->crf[crfD] = ret;
if (unlikely(ret == 0x01UL
&& (float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d)))) {
/* sNaN comparison */
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
}
}
void helper_fcmpo (uint64_t arg1, uint64_t arg2, uint32_t crfD)
{
CPU_DoubleU farg1, farg2;
uint32_t ret = 0;
farg1.ll = arg1;
farg2.ll = arg2;
if (unlikely(float64_is_nan(farg1.d) ||
float64_is_nan(farg2.d))) {
ret = 0x01UL;
} else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
ret = 0x08UL;
} else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
ret = 0x04UL;
} else {
ret = 0x02UL;
}
env->fpscr &= ~(0x0F << FPSCR_FPRF);
env->fpscr |= ret << FPSCR_FPRF;
env->crf[crfD] = ret;
if (unlikely (ret == 0x01UL)) {
if (float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d)) {
/* sNaN comparison */
@ -1663,18 +1680,7 @@ uint32_t helper_fcmpo (uint64_t arg1, uint64_t arg2)
/* qNaN comparison */
fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC);
}
} else {
if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
ret = 0x08UL;
} else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
ret = 0x04UL;
} else {
ret = 0x02UL;
}
}
env->fpscr &= ~(0x0F << FPSCR_FPRF);
env->fpscr |= ret << FPSCR_FPRF;
return ret;
}
#if !defined (CONFIG_USER_ONLY)