aboutsummaryrefslogtreecommitdiff
path: root/target-ppc
diff options
context:
space:
mode:
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-11-11 00:33:08 +0000
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-11-11 00:33:08 +0000
commit9c7e37e7fad48f6e7bbafa29f7980a4a9bf191b7 (patch)
treefc76114a27a92796895ecb341b875c19ef0d5d07 /target-ppc
parentc3e10c7b4377c1cbc0a4fbc12312c2cf41c0cda7 (diff)
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
Diffstat (limited to 'target-ppc')
-rw-r--r--target-ppc/op.c4
-rw-r--r--target-ppc/op_helper.c14
2 files changed, 10 insertions, 8 deletions
diff --git a/target-ppc/op.c b/target-ppc/op.c
index bbc5c5b9a5..81c426c1a7 100644
--- a/target-ppc/op.c
+++ b/target-ppc/op.c
@@ -2199,9 +2199,9 @@ void OPPROTO op_store_601_batu (void)
/* XXX: those micro-ops need tests ! */
void OPPROTO op_POWER_abs (void)
{
- if (T0 == INT32_MIN)
+ if ((int32_t)T0 == INT32_MIN)
T0 = INT32_MAX;
- else if (T0 < 0)
+ else if ((int32_t)T0 < 0)
T0 = -T0;
RETURN();
}
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 75bf33bff1..7d1411a1fd 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -1512,14 +1512,16 @@ void do_td (int flags)
/* PowerPC 601 specific instructions (POWER bridge) */
void do_POWER_abso (void)
{
- if ((uint32_t)T0 == INT32_MIN) {
+ if ((int32_t)T0 == INT32_MIN) {
T0 = INT32_MAX;
xer_ov = 1;
- xer_so = 1;
- } else {
+ } else if ((int32_t)T0 < 0) {
T0 = -T0;
xer_ov = 0;
+ } else {
+ xer_ov = 0;
}
+ xer_so |= xer_ov;
}
void do_POWER_clcs (void)
@@ -1896,8 +1898,8 @@ void do_ev##name (void) \
/* Fixed-point vector arithmetic */
static always_inline uint32_t _do_eabs (uint32_t val)
{
- if (val != 0x80000000)
- val &= ~0x80000000;
+ if ((val & 0x80000000) && val != 0x80000000)
+ val -= 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)
{
if (val != 0x80000000)
- val ^= 0x80000000;
+ val -= val;
return val;
}