Fix POWER abs & abso computation.

Fix PowerPC SPE evabs & evneg (thanks to Fabrice Bellard for reporting the bug)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3575 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
j_mayer 2007-11-11 00:33:08 +00:00
parent c3e10c7b43
commit 9c7e37e7fa
2 changed files with 10 additions and 8 deletions

View File

@ -2199,9 +2199,9 @@ void OPPROTO op_store_601_batu (void)
/* XXX: those micro-ops need tests ! */ /* XXX: those micro-ops need tests ! */
void OPPROTO op_POWER_abs (void) void OPPROTO op_POWER_abs (void)
{ {
if (T0 == INT32_MIN) if ((int32_t)T0 == INT32_MIN)
T0 = INT32_MAX; T0 = INT32_MAX;
else if (T0 < 0) else if ((int32_t)T0 < 0)
T0 = -T0; T0 = -T0;
RETURN(); RETURN();
} }

View File

@ -1512,14 +1512,16 @@ void do_td (int flags)
/* PowerPC 601 specific instructions (POWER bridge) */ /* PowerPC 601 specific instructions (POWER bridge) */
void do_POWER_abso (void) void do_POWER_abso (void)
{ {
if ((uint32_t)T0 == INT32_MIN) { if ((int32_t)T0 == INT32_MIN) {
T0 = INT32_MAX; T0 = INT32_MAX;
xer_ov = 1; xer_ov = 1;
xer_so = 1; } else if ((int32_t)T0 < 0) {
} else {
T0 = -T0; T0 = -T0;
xer_ov = 0; xer_ov = 0;
} else {
xer_ov = 0;
} }
xer_so |= xer_ov;
} }
void do_POWER_clcs (void) void do_POWER_clcs (void)
@ -1896,8 +1898,8 @@ void do_ev##name (void) \
/* Fixed-point vector arithmetic */ /* Fixed-point vector arithmetic */
static always_inline uint32_t _do_eabs (uint32_t val) static always_inline uint32_t _do_eabs (uint32_t val)
{ {
if (val != 0x80000000) if ((val & 0x80000000) && val != 0x80000000)
val &= ~0x80000000; val -= val;
return val; return val;
} }
@ -1923,7 +1925,7 @@ static always_inline int _do_ecntlzw (uint32_t val)
static always_inline uint32_t _do_eneg (uint32_t val) static always_inline uint32_t _do_eneg (uint32_t val)
{ {
if (val != 0x80000000) if (val != 0x80000000)
val ^= 0x80000000; val -= val;
return val; return val;
} }