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:
parent
b12363e1b7
commit
9a819377d8
@ -63,8 +63,8 @@ DEF_HELPER_1(fpscr_setbit, void, i32)
|
||||
DEF_HELPER_1(float64_to_float32, i32, i64)
|
||||
DEF_HELPER_1(float32_to_float64, i64, i32)
|
||||
|
||||
DEF_HELPER_2(fcmpo, i32, i64, i64)
|
||||
DEF_HELPER_2(fcmpu, i32, i64, i64)
|
||||
DEF_HELPER_3(fcmpo, void, i64, i64, i32)
|
||||
DEF_HELPER_3(fcmpu, void, i64, i64, i32)
|
||||
|
||||
DEF_HELPER_1(fctiw, i64, i64)
|
||||
DEF_HELPER_1(fctiwz, i64, i64)
|
||||
|
@ -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)
|
||||
|
@ -2249,26 +2249,30 @@ GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
|
||||
/* fcmpo */
|
||||
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
|
||||
{
|
||||
TCGv crf;
|
||||
if (unlikely(!ctx->fpu_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_FPU);
|
||||
return;
|
||||
}
|
||||
gen_reset_fpstatus();
|
||||
gen_helper_fcmpo(cpu_crf[crfD(ctx->opcode)],
|
||||
cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
|
||||
crf = tcg_const_i32(crfD(ctx->opcode));
|
||||
gen_helper_fcmpo(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
|
||||
tcg_temp_free(crf);
|
||||
gen_helper_float_check_status();
|
||||
}
|
||||
|
||||
/* fcmpu */
|
||||
GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
|
||||
{
|
||||
TCGv crf;
|
||||
if (unlikely(!ctx->fpu_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_FPU);
|
||||
return;
|
||||
}
|
||||
gen_reset_fpstatus();
|
||||
gen_helper_fcmpu(cpu_crf[crfD(ctx->opcode)],
|
||||
cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
|
||||
crf = tcg_const_i32(crfD(ctx->opcode));
|
||||
gen_helper_fcmpu(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
|
||||
tcg_temp_free(crf);
|
||||
gen_helper_float_check_status();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user