OSDN Git Service

sim: bfin: handle AN (negative overflows) in dsp mult insns
authorvapier <vapier>
Tue, 15 Mar 2011 20:09:39 +0000 (20:09 +0000)
committervapier <vapier>
Tue, 15 Mar 2011 20:09:39 +0000 (20:09 +0000)
The current dsp mult handler does not take care of overflows which turn
values negative (and thus set AN in ASTAT).  So implement it.

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 d8cbc40..45bf0a8 100644 (file)
@@ -1,5 +1,12 @@
 2011-03-15  Robin Getz  <robin.getz@analog.com>
 
+       * bfin-sim.c (decode_macfunc): New neg parameter.  Set when the
+       high bit is set after extract_mult.
+       (decode_dsp32mac_0): Declare n_1 and n_0.  Pass to the decode_macfunc
+       functions.  Use these to update the AN bit.
+
+2011-03-15  Robin Getz  <robin.getz@analog.com>
+
        * bfin-sim.c (decode_dsp32mult_0): Declare v_i0 and v_i1.  Pass to
        the extract_mult functions.  Include these when updating the V, VS,
        and V_COPY bits.
index 5df7340..ba0e0c2 100644 (file)
@@ -1562,10 +1562,11 @@ extract_mult (SIM_CPU *cpu, bu64 res, int mmod, int MM,
 
 static bu32
 decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0,
-               int src1, int mmod, int MM, int fullword, bu32 *overflow)
+               int src1, int mmod, int MM, int fullword, bu32 *overflow,
+               bu32 *neg)
 {
   bu64 acc;
-  bu32 sat = 0, tsat;
+  bu32 sat = 0, tsat, ret;
 
   /* Sign extend accumulator if necessary, otherwise unsigned.  */
   if (mmod == 0 || mmod == M_T || mmod == M_IS || mmod == M_ISS2
@@ -1658,6 +1659,9 @@ decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0,
        default:
          illegal_instruction (cpu);
        }
+
+      if (acc & 0x8000000000ull)
+       *neg = 1;
     }
 
   STORE (AXREG (which), (acc >> 32) & 0xff);
@@ -1666,7 +1670,20 @@ decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0,
   if (sat)
     STORE (ASTATREG (avs[which]), sat);
 
-  return extract_mult (cpu, acc, mmod, MM, fullword, overflow);
+  ret = extract_mult (cpu, acc, mmod, MM, fullword, overflow);
+
+  if (!fullword)
+    {
+      if (ret & 0x8000)
+       *neg = 1;
+    }
+  else
+    {
+      if (ret & 0x80000000)
+       *neg = 1;
+    }
+
+  return ret;
 }
 
 bu32
@@ -3702,7 +3719,7 @@ decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
   int h01  = ((iw1 >> DSP32Mac_h01_bits) & DSP32Mac_h01_mask);
 
   bu32 res = DREG (dst);
-  bu32 v_i = 0, zero = 0;
+  bu32 v_i = 0, zero = 0, n_1 = 0, n_0 = 0;
 
   static const char * const ops[] = { "=", "+=", "-=" };
   char _buf[128], *buf = _buf;
@@ -3727,7 +3744,7 @@ decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
   if (w1 == 1 || op1 != 3)
     {
       bu32 res1 = decode_macfunc (cpu, 1, op1, h01, h11, src0,
-                                 src1, mmod, MM, P, &v_i);
+                                 src1, mmod, MM, P, &v_i, &n_1);
 
       if (w1)
        buf += sprintf (buf, P ? "R%i" : "R%i.H", dst + P);
@@ -3773,7 +3790,7 @@ decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
   if (w0 == 1 || op0 != 3)
     {
       bu32 res0 = decode_macfunc (cpu, 0, op0, h00, h10, src0,
-                                 src1, mmod, 0, P, &v_i);
+                                 src1, mmod, 0, P, &v_i, &n_0);
 
       if (w0)
        buf += sprintf (buf, P ? "R%i" : "R%i.L", dst);
@@ -3822,8 +3839,16 @@ decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
       if (v_i)
        SET_ASTATREG (vs, v_i);
     }
-  if (op0 == 3 || op1 == 3)
-    SET_ASTATREG (az, zero);
+
+  if ((w0 == 1 && op0 == 3) || (w1 == 1 && op1 == 3))
+    {
+      SET_ASTATREG (az, zero);
+      if (!(w0 == 1 && op0 == 3))
+       n_0 = 0;
+      if (!(w1 == 1 && op1 == 3))
+       n_1 = 0;
+      SET_ASTATREG (an, n_1 | n_0);
+    }
 }
 
 static void