summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2011-06-18 20:59:24 +0000
committerMike Frysinger <vapier@gentoo.org>2011-06-18 20:59:24 +0000
commit99dcc4dc6501c726df79173fa254faebc68a486d (patch)
tree7b6f02f91d68dbd0e7627569a616a75bd72a5ae4
parent4bd2c0c31ccea3032031648e7497bb7d1c04cc39 (diff)
downloadppe42-binutils-99dcc4dc6501c726df79173fa254faebc68a486d.tar.gz
ppe42-binutils-99dcc4dc6501c726df79173fa254faebc68a486d.zip
sim: bfin: handle odd shift values with shift insns
The shift magnitude is a 5-bit signed value. When it is between 0 and 15, then we do the requested shift, but when it is outside of that, we have to do the opposite. That means we flip between lshift and ashiftrt to match the hardware. Signed-off-by: Robin Getz <robin.getz@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-rw-r--r--sim/bfin/ChangeLog7
-rw-r--r--sim/bfin/bfin-sim.c36
2 files changed, 36 insertions, 7 deletions
diff --git a/sim/bfin/ChangeLog b/sim/bfin/ChangeLog
index ffd9ff2252..c702981646 100644
--- a/sim/bfin/ChangeLog
+++ b/sim/bfin/ChangeLog
@@ -1,5 +1,12 @@
2011-06-18 Robin Getz <robin.getz@analog.com>
+ * bfin-sim.c (decode_dsp32shiftimm_0): With left shift vector insns,
+ call lshift only when count is positive. Otherwise, call ashiftrt.
+ With arithmetic right shift insns, call ashiftrt when the value is
+ small enough, otherwise call lshift.
+
+2011-06-18 Robin Getz <robin.getz@analog.com>
+
* bfin-sim.c (extract_mult): Call saturate_s16 directly when
mmod is M_IH rather than computing the result by hand.
diff --git a/sim/bfin/bfin-sim.c b/sim/bfin/bfin-sim.c
index 38e5fe1ebd..11eea3a234 100644
--- a/sim/bfin/bfin-sim.c
+++ b/sim/bfin/bfin-sim.c
@@ -5678,7 +5678,10 @@ decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
TRACE_INSN (cpu, "R%i.%c = R%i.%c >>> %i;",
dst0, (HLs & 2) ? 'H' : 'L',
src1, (HLs & 1) ? 'H' : 'L', newimmag);
- result = ashiftrt (cpu, in, newimmag, 16);
+ if (newimmag > 16)
+ result = lshift (cpu, in, 16 - (newimmag & 0xF), 16, 0);
+ else
+ result = ashiftrt (cpu, in, newimmag, 16);
}
else if (sop == 1 && bit8 == 0)
{
@@ -5786,9 +5789,18 @@ decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
bu32 astat;
TRACE_INSN (cpu, "R%i = R%i << %i (V,S);", dst0, src1, count);
- val0 = lshift (cpu, val0, count, 16, 1);
- astat = ASTAT;
- val1 = lshift (cpu, val1, count, 16, 1);
+ if (count >= 0)
+ {
+ val0 = lshift (cpu, val0, count, 16, 1);
+ astat = ASTAT;
+ val1 = lshift (cpu, val1, count, 16, 1);
+ }
+ else
+ {
+ val0 = ashiftrt (cpu, val0, -count, 16);
+ astat = ASTAT;
+ val1 = ashiftrt (cpu, val1, -count, 16);
+ }
SET_ASTAT (ASTAT | astat);
STORE (DREG (dst0), (val0 << 16) | val1);
@@ -5833,9 +5845,19 @@ decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
TRACE_INSN (cpu, "R%i = R%i >>> %i %s;", dst0, src1, count,
sop == 0 ? "(V)" : "(V,S)");
- val0 = ashiftrt (cpu, val0, count, 16);
- astat = ASTAT;
- val1 = ashiftrt (cpu, val1, count, 16);
+ if (count & 0x10)
+ {
+ val0 = lshift (cpu, val0, 16 - (count & 0xF), 16, 0);
+ astat = ASTAT;
+ val1 = lshift (cpu, val1, 16 - (count & 0xF), 16, 0);
+ }
+ else
+ {
+ val0 = ashiftrt (cpu, val0, count, 16);
+ astat = ASTAT;
+ val1 = ashiftrt (cpu, val1, count, 16);
+ }
+
SET_ASTAT (ASTAT | astat);
STORE (DREG (dst0), REG_H_L (val1 << 16, val0));
OpenPOWER on IntegriCloud