diff options
author | Richard Sandiford <rdsandiford@googlemail.com> | 2004-03-01 09:33:48 +0000 |
---|---|---|
committer | Richard Sandiford <rdsandiford@googlemail.com> | 2004-03-01 09:33:48 +0000 |
commit | 8b73069fed6ec6b73e35eccdf186887d89ecb84b (patch) | |
tree | 00fb7c94453402251df5876c67b036abdf8437b4 /sim/frv/frv.c | |
parent | 8ae0baa2685df96375cc43b44b5632044288f74a (diff) | |
download | binutils-8b73069fed6ec6b73e35eccdf186887d89ecb84b.tar.gz binutils-8b73069fed6ec6b73e35eccdf186887d89ecb84b.tar.bz2 binutils-8b73069fed6ec6b73e35eccdf186887d89ecb84b.zip |
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/frv.c')
-rw-r--r-- | sim/frv/frv.c | 57 |
1 files changed, 43 insertions, 14 deletions
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). */ |