sim: bfin: handle odd shift values with shift insns
authorMike Frysinger <vapier@gentoo.org>
Sat, 18 Jun 2011 20:59:24 +0000 (20:59 +0000)
committerMike Frysinger <vapier@gentoo.org>
Sat, 18 Jun 2011 20:59:24 +0000 (20:59 +0000)
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>
sim/bfin/ChangeLog
sim/bfin/bfin-sim.c

index ffd9ff2252dbddeff517f9beea05039de5398796..c7029816466f55512e5c8ddb76091e5c274f4189 100644 (file)
@@ -1,3 +1,10 @@
+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
index 38e5fe1ebdbd7b14cf98b19d092e053e283072e2..11eea3a234b485021474637793944c11b4649050 100644 (file)
@@ -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));