summaryrefslogtreecommitdiff
path: root/sim/frv
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@nildram.co.uk>2004-03-01 09:33:48 +0000
committerRichard Sandiford <rsandifo@nildram.co.uk>2004-03-01 09:33:48 +0000
commitb248554e3e5a47261dc6acae90da4e1dc7279f7d (patch)
tree6d71f9ac5dd02b0c8ea15a2ec95a3c1ecc675b8a /sim/frv
parent334cc55378694196689a48bc065b1378ec04a47c (diff)
downloadgdb-b248554e3e5a47261dc6acae90da4e1dc7279f7d.tar.gz
sim/frv/
* frv.c (frvbf_iacc_cut): Rework, taking rounding into account. testsuite/ * sim/frv/fr400/scutss.cgs: Fix tests to account for rounding. Add some new ones.
Diffstat (limited to 'sim/frv')
-rw-r--r--sim/frv/ChangeLog4
-rw-r--r--sim/frv/frv.c57
2 files changed, 47 insertions, 14 deletions
diff --git a/sim/frv/ChangeLog b/sim/frv/ChangeLog
index 41462a3dbd0..652c956fb27 100644
--- a/sim/frv/ChangeLog
+++ b/sim/frv/ChangeLog
@@ -1,5 +1,9 @@
2004-03-01 Richard Sandiford <rsandifo@redhat.com>
+ * frv.c (frvbf_iacc_cut): Rework, taking rounding into account.
+
+2004-03-01 Richard Sandiford <rsandifo@redhat.com>
+
* decode.c, decode.h, model.c, sem.c: Regenerate.
2003-11-24 Kevin Buettner <kevinb@redhat.com>
diff --git a/sim/frv/frv.c b/sim/frv/frv.c
index de1ff1d0529..2640b1c29c6 100644
--- a/sim/frv/frv.c
+++ b/sim/frv/frv.c
@@ -1,5 +1,6 @@
/* frv simulator support code
- Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004 Free Software
+ Foundation, Inc.
Contributed by Red Hat.
This file is part of the GNU simulators.
@@ -1100,25 +1101,53 @@ frvbf_media_cut_ss (SIM_CPU *current_cpu, DI acc, SI cut_point)
SI
frvbf_iacc_cut (SIM_CPU *current_cpu, DI acc, SI cut_point)
{
- /* The cut point is the lower 6 bits (signed) of what we are passed. */
+ DI lower, upper;
+
+ /* The cut point is the lower 7 bits (signed) of what we are passed. */
cut_point = cut_point << 25 >> 25;
- if (cut_point <= -32)
- cut_point = -31; /* Special case for full shiftout. */
+ /* Conceptually, the operation is on a 128-bit sign-extension of ACC.
+ The top bit of the return value corresponds to bit (63 - CUT_POINT)
+ of this 128-bit value.
- /* Negative cuts (cannot saturate). */
+ Since we can't deal with 128-bit values very easily, convert the
+ operation into an equivalent 64-bit one. */
if (cut_point < 0)
- return acc >> (32 + -cut_point);
+ {
+ /* Avoid an undefined shift operation. */
+ if (cut_point == -64)
+ acc >>= 63;
+ else
+ acc >>= -cut_point;
+ cut_point = 0;
+ }
- /* Positive cuts will saturate if significant bits are shifted out. */
- if (acc != ((acc << cut_point) >> cut_point))
- if (acc >= 0)
- return 0x7fffffff;
- else
- return 0x80000000;
+ /* Get the shifted but unsaturated result. Set LOWER to the lowest
+ 32 bits of the result and UPPER to the result >> 31. */
+ if (cut_point < 32)
+ {
+ /* The cut loses the (32 - CUT_POINT) least significant bits.
+ Round the result up if the most significant of these lost bits
+ is 1. */
+ lower = acc >> (32 - cut_point);
+ if (lower < 0x7fffffff)
+ if (acc & LSBIT64 (32 - cut_point - 1))
+ lower++;
+ upper = lower >> 31;
+ }
+ else
+ {
+ lower = acc << (cut_point - 32);
+ upper = acc >> (63 - cut_point);
+ }
- /* No saturate, just cut. */
- return ((acc << cut_point) >> 32);
+ /* Saturate the result. */
+ if (upper < -1)
+ return ~0x7fffffff;
+ else if (upper > 0)
+ return 0x7fffffff;
+ else
+ return lower;
}
/* Compute the result of shift-left-arithmetic-with-saturation (SLASS). */