gas/
[deliverable/binutils-gdb.git] / sim / bfin / bfin-sim.c
index 03b9d7a12cebc1f7180125455e9e91d137bb1234..2fa82abdd999fd904fd43be9979e697cbb42d67a 100644 (file)
@@ -1,6 +1,6 @@
 /* Simulator for Analog Devices Blackfin processors.
 
-   Copyright (C) 2005-2012 Free Software Foundation, Inc.
+   Copyright (C) 2005-2013 Free Software Foundation, Inc.
    Contributed by Analog Devices, Inc.
 
    This file is part of simulators.
@@ -5206,7 +5206,16 @@ decode_dsp32shift_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
       if (shft <= 0)
        val = ashiftrt (cpu, val, -shft, 16);
       else
-       val = lshift (cpu, val, shft, 16, sop == 1, 1);
+       {
+         int sgn = (val >> 15) & 0x1;
+
+         val = lshift (cpu, val, shft, 16, sop == 1, 1);
+         if (((val >> 15) & 0x1) != sgn)
+           {
+             SET_ASTATREG (v, 1);
+             SET_ASTATREG (vs, 1);
+           }
+       }
 
       if ((HLs & 2) == 0)
        STORE (DREG (dst0), REG_H_L (DREG (dst0), val));
@@ -5258,42 +5267,40 @@ decode_dsp32shift_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
   else if (sop == 0 && sopcde == 3 && (HLs == 0 || HLs == 1))
     {
       bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
-      bu64 val = get_extended_acc (cpu, HLs);
+      bu64 acc = get_extended_acc (cpu, HLs);
+      bu64 val;
 
       HLs = !!HLs;
       TRACE_INSN (cpu, "A%i = ASHIFT A%i BY R%i.L;", HLs, HLs, src0);
-      TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i", HLs, val, shft);
+      TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i", HLs, acc, shft);
 
       if (shft <= 0)
-       val = ashiftrt (cpu, val, -shft, 40);
+       val = ashiftrt (cpu, acc, -shft, 40);
       else
-       val = lshift (cpu, val, shft, 40, 0, 0);
+       val = lshift (cpu, acc, shft, 40, 0, 0);
 
       STORE (AXREG (HLs), (val >> 32) & 0xff);
       STORE (AWREG (HLs), (val & 0xffffffff));
-      STORE (ASTATREG (av[HLs]), val == 0);
-      if (val == 0)
-       STORE (ASTATREG (avs[HLs]), 1);
+      STORE (ASTATREG (av[HLs]), 0);
     }
   else if (sop == 1 && sopcde == 3 && (HLs == 0 || HLs == 1))
     {
       bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
+      bu64 acc = get_unextended_acc (cpu, HLs);
       bu64 val;
 
       HLs = !!HLs;
       TRACE_INSN (cpu, "A%i = LSHIFT A%i BY R%i.L;", HLs, HLs, src0);
-      val = get_unextended_acc (cpu, HLs);
+      TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i", HLs, acc, shft);
 
       if (shft <= 0)
-       val = lshiftrt (cpu, val, -shft, 40);
+       val = lshiftrt (cpu, acc, -shft, 40);
       else
-       val = lshift (cpu, val, shft, 40, 0, 0);
+       val = lshift (cpu, acc, shft, 40, 0, 0);
 
       STORE (AXREG (HLs), (val >> 32) & 0xff);
       STORE (AWREG (HLs), (val & 0xffffffff));
-      STORE (ASTATREG (av[HLs]), val == 0);
-      if (val == 0)
-       STORE (ASTATREG (avs[HLs]), 1);
+      STORE (ASTATREG (av[HLs]), 0);
     }
   else if ((sop == 0 || sop == 1) && sopcde == 1)
     {
@@ -5315,9 +5322,18 @@ decode_dsp32shift_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
        }
       else
        {
+         int sgn0 = (val0 >> 15) & 0x1;
+         int sgn1 = (val1 >> 15) & 0x1;
+
          val0 = lshift (cpu, val0, shft, 16, sop == 1, 1);
          astat = ASTAT;
          val1 = lshift (cpu, val1, shft, 16, sop == 1, 1);
+
+         if ((sgn0 != ((val0 >> 15) & 0x1)) || (sgn1 != ((val1 >> 15) & 0x1)))
+           {
+             SET_ASTATREG (v, 1);
+             SET_ASTATREG (vs, 1);
+           }
        }
       SET_ASTAT (ASTAT | astat);
       STORE (DREG (dst0), (val1 << 16) | val0);
@@ -5342,7 +5358,16 @@ decode_dsp32shift_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
            STORE (DREG (dst0), ashiftrt (cpu, v, -shft, 32));
        }
       else
-       STORE (DREG (dst0), lshift (cpu, v, shft, 32, sop == 1, 1));
+       {
+         bu32 val = lshift (cpu, v, shft, 32, sop == 1, 1);
+
+         STORE (DREG (dst0), val);
+         if (((v >> 31) & 0x1) != ((val >> 31) & 0x1))
+           {
+             SET_ASTATREG (v, 1);
+             SET_ASTATREG (vs, 1);
+           }
+       }
     }
   else if (sop == 3 && sopcde == 2)
     {
@@ -5716,6 +5741,26 @@ decode_dsp32shift_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
     illegal_instruction (cpu);
 }
 
+static bu64
+sgn_extend (bu40 org, bu40 val, int size)
+{
+  bu64 ret = val;
+
+  if (org & (1ULL << (size - 1)))
+    {
+      /* We need to shift in to the MSB which is set.  */
+      int n;
+
+      for (n = 40; n >= 0; n--)
+       if (ret & (1ULL << n))
+         break;
+      ret |= (-1ULL << n);
+    }
+  else
+    ret &= ~(-1ULL << 39);
+
+  return ret;
+}
 static void
 decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
 {
@@ -5750,7 +5795,14 @@ decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
                      dst0, (HLs & 2) ? 'H' : 'L',
                      src1, (HLs & 1) ? 'H' : 'L', newimmag);
          if (newimmag > 16)
-           result = lshift (cpu, in, 16 - (newimmag & 0xF), 16, 0, 1);
+           {
+             result = lshift (cpu, in, 16 - (newimmag & 0xF), 16, 0, 1);
+             if (((result >> 15) & 0x1) != ((in >> 15) & 0x1))
+               {
+                 SET_ASTATREG (v, 1);
+                 SET_ASTATREG (vs, 1);
+               }
+           }
          else
            result = ashiftrt (cpu, in, newimmag, 16);
        }
@@ -5765,8 +5817,37 @@ decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
        {
          TRACE_INSN (cpu, "R%i.%c = R%i.%c >>> %i (S);",
                      dst0, (HLs & 2) ? 'H' : 'L',
-                     src1, (HLs & 1) ? 'H' : 'L', immag);
-         result = lshift (cpu, in, immag, 16, 1, 1);
+                     src1, (HLs & 1) ? 'H' : 'L', newimmag);
+         if (newimmag > 16)
+           {
+             int shift = 32 - newimmag;
+             bu16 inshift = in << shift;
+
+             if (((inshift & ~0xFFFF)
+                  && ((inshift & ~0xFFFF) >> 16) != ~(~0 << shift))
+                 || (inshift & 0x8000) != (in & 0x8000))
+               {
+                 if (in & 0x8000)
+                   result = 0x8000;
+                 else
+                   result = 0x7fff;
+                 SET_ASTATREG (v, 1);
+                 SET_ASTATREG (vs, 1);
+               }
+             else
+               {
+                 result = inshift;
+                 SET_ASTATREG (v, 0);
+               }
+
+             SET_ASTATREG (az, !result);
+             SET_ASTATREG (an, !!(result & 0x8000));
+           }
+         else
+           {
+             result = ashiftrt (cpu, in, newimmag, 16);
+             result = sgn_extend (in, result, 16);
+           }
        }
       else if (sop == 2 && bit8)
        {
@@ -5808,22 +5889,23 @@ decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
   else if (sop == 0 && sopcde == 3 && bit8 == 1)
     {
       /* Arithmetic shift, so shift in sign bit copies.  */
-      bu64 acc;
+      bu64 acc, val;
       int shift = uimm5 (newimmag);
       HLs = !!HLs;
 
       TRACE_INSN (cpu, "A%i = A%i >>> %i;", HLs, HLs, shift);
 
       acc = get_extended_acc (cpu, HLs);
-      acc >>= shift;
+      val = acc >> shift;
+
       /* Sign extend again.  */
-      if (acc & (1ULL << 39))
-       acc |= -(1ULL << 39);
-      else
-       acc &= ~(-(1ULL << 39));
+      val = sgn_extend (acc, val, 40);
 
-      STORE (AXREG (HLs), (acc >> 32) & 0xFF);
-      STORE (AWREG (HLs), acc & 0xFFFFFFFF);
+      STORE (AXREG (HLs), (val >> 32) & 0xFF);
+      STORE (AWREG (HLs), val & 0xFFFFFFFF);
+      STORE (ASTATREG (an), !!(val & (1ULL << 39)));
+      STORE (ASTATREG (az), !val);
+      STORE (ASTATREG (av[HLs]), 0);
     }
   else if ((sop == 0 && sopcde == 3 && bit8 == 0)
           || (sop == 1 && sopcde == 3))
@@ -5922,11 +6004,20 @@ 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)");
 
-      if (count & 0x10)
+      if (count > 16)
        {
+         int sgn0 = (val0 >> 15) & 0x1;
+         int sgn1 = (val1 >> 15) & 0x1;
+
          val0 = lshift (cpu, val0, 16 - (count & 0xF), 16, 0, 1);
          astat = ASTAT;
          val1 = lshift (cpu, val1, 16 - (count & 0xF), 16, 0, 1);
+
+         if ((sgn0 != ((val0 >> 15) & 0x1)) || (sgn1 != ((val1 >> 15) & 0x1)))
+           {
+             SET_ASTATREG (v, 1);
+             SET_ASTATREG (vs, 1);
+           }
        }
       else
        {
This page took 0.026497 seconds and 4 git commands to generate.