This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] sim: bfin: handle V/VS saturation in dsp mac insns


From: Robin Getz <robin.getz@analog.com>

Some saturation cases with dsp mac insns were not setting the V flag.
So implement that part and split up the logic between the dual macs.

Committed.

Signed-off-by: Robin Getz <robin.getz@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>

2011-06-18  Robin Getz  <robin.getz@analog.com>

	* bfin-sim.c (decode_macfunc): Add nosat_acc to track acc value
	before saturation, set sat when more cases saturate, and set the
	overflow bit based on these results.  For M_TFU, M_IU, M_FU, and
	M_W32, change the max values compared against.
	(decode_dsp32mac_0): Delete v_i and add v_0 and v_1.  Pass v_1
	when processing MAC1 and pass v_0 when processing MAC0.  Combine
	the results into the V/VS ASTAT bits.
---
 sim/bfin/bfin-sim.c |   86 +++++++++++++++++++++++++++++----------------------
 1 files changed, 49 insertions(+), 37 deletions(-)

diff --git a/sim/bfin/bfin-sim.c b/sim/bfin/bfin-sim.c
index 71fda3e..38e5fe1 100644
--- a/sim/bfin/bfin-sim.c
+++ b/sim/bfin/bfin-sim.c
@@ -1591,6 +1580,9 @@ decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0,
   if (op != 3)
     {
       bu8 sgn0 = (acc >> 31) & 1;
+      bu8 sgn40 = (acc >> 39) & 1;
+      bu40 nosat_acc;
+
       /* This can't saturate, so we don't keep track of the sat flag.  */
       bu64 res = decode_multfunc (cpu, h0, h1, src0, src1, mmod,
 				  MM, &tsat);
@@ -1610,6 +1602,7 @@ decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0,
 	  break;
 	}
 
+      nosat_acc = acc;
       /* Saturate.  */
       switch (mmod)
 	{
@@ -1624,20 +1617,20 @@ decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0,
 	    acc = 0x7fffffffffull, sat = 1;
 	  break;
 	case M_TFU:
-	  if (!MM && acc > 0xFFFFFFFFFFull)
-	    acc = 0x0, sat = 1;
-	  if (MM && acc > 0xFFFFFFFF)
-	    acc &= 0xFFFFFFFF;
+	  if (!MM && (bs64)acc < 0)
+	    acc = 0, sat = 1;
+	  if (!MM && (bs64)acc > 0xFFFFFFFFFFull)
+	    acc = 0xFFFFFFFFFFull, sat = 1;
 	  break;
 	case M_IU:
-	  if (acc & 0x8000000000000000ull)
+	  if (!MM && acc & 0x8000000000000000ull)
 	    acc = 0x0, sat = 1;
-	  if (acc > 0xFFFFFFFFFFull)
-	    acc &= 0xFFFFFFFFFFull, sat = 1;
-	  if (MM && acc > 0xFFFFFFFF)
-	    acc &= 0xFFFFFFFF;
-	  if (acc & 0x80000000)
-	    acc |= 0xffffffff00000000ull;
+	  if (!MM && acc > 0xFFFFFFFFFFull)
+	    acc = 0xFFFFFFFFFFull, sat = 1;
+	  if (MM && acc > 0xFFFFFFFFFFull)
+	    acc &= 0xFFFFFFFFFFull;
+	  if (acc & 0x8000000000ull)
+	    acc |= 0xffffff0000000000ull;
 	  break;
 	case M_FU:
 	  if (!MM && (bs64)acc < 0)
@@ -1648,8 +1641,8 @@ decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0,
 	    acc = 0xFFFFFFFFFFull, sat = 1;
 	  if (MM && acc > 0xFFFFFFFFFFull)
 	    acc &= 0xFFFFFFFFFFull;
-	  if (MM && acc & 0x80000000)
-	    acc |= 0xffffffff00000000ull;
+	  if (MM && acc & 0x8000000000ull)
+	    acc |= 0xffffff0000000000ull;
 	  break;
 	case M_IH:
 	  if ((bs64)acc < -0x80000000ll)
@@ -1658,12 +1651,18 @@ decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0,
 	    acc = 0x7fffffffull, sat = 1;
 	  break;
 	case M_W32:
-	  if (sgn0 && (sgn0 != ((acc >> 31) & 1))
-	      && (((acc >> 32) & 0xFF) == 0xff))
-	    acc = 0x80000000;
+	  /* check max negative value */
+	  if (sgn40 && ((acc >> 31) != 0x1ffffffff)
+	      && ((acc >> 31) != 0x0))
+	    acc = 0x80000000, sat = 1;
+	  if (!sat && !sgn40 && ((acc >> 31) != 0x0)
+	      && ((acc >> 31) != 0x1ffffffff))
+	    acc = 0x7FFFFFFF, sat = 1;
 	  acc &= 0xffffffff;
 	  if (acc & 0x80000000)
 	    acc |= 0xffffffff00000000ull;
+	  if (tsat)
+	    sat = 1;
 	  break;
 	default:
 	  illegal_instruction (cpu);
@@ -1677,6 +1676,15 @@ decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0,
       STORE (ASTATREG (av[which]), sat);
       if (sat)
 	STORE (ASTATREG (avs[which]), sat);
+
+      /* Figure out the overflow bit.  */
+      if (sat)
+	{
+	  if (fullword)
+	    *overflow = 1;
+	  else
+	    ret = extract_mult (cpu, nosat_acc, mmod, MM, fullword, overflow);
+	}
     }
 
   ret = extract_mult (cpu, acc, mmod, MM, fullword, overflow);
@@ -3727,7 +3735,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, n_1 = 0, n_0 = 0;
+  bu32 v_0 = 0, v_1 = 0, zero = 0, n_1 = 0, n_0 = 0;
 
   static const char * const ops[] = { "=", "+=", "-=" };
   char _buf[128], *buf = _buf;
@@ -3752,7 +3760,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, &n_1);
+				  src1, mmod, MM, P, &v_1, &n_1);
 
       if (w1)
 	buf += sprintf (buf, P ? "R%i" : "R%i.H", dst + P);
@@ -3784,6 +3792,8 @@ decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
 	      res = REG_H_L (res1 << 16, res);
 	    }
 	}
+      else
+	v_1 = 0;
 
       if (w0 == 1 || op0 != 3)
 	{
@@ -3798,7 +3808,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, &n_0);
+				  src1, mmod, 0, P, &v_0, &n_0);
 
       if (w0)
 	buf += sprintf (buf, P ? "R%i" : "R%i.L", dst);
@@ -3830,6 +3840,8 @@ decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
 	      res = REG_H_L (res, res0);
 	    }
 	}
+      else
+	v_0 = 0;
     }
 
   TRACE_INSN (cpu, "%s%s;", _buf, mac_optmode (mmod, _MM));
@@ -3837,15 +3849,15 @@ decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
   if (!P && (w0 || w1))
     {
       STORE (DREG (dst), res);
-      SET_ASTATREG (v, v_i);
-      if (v_i)
-	SET_ASTATREG (vs, v_i);
+      SET_ASTATREG (v, v_0 | v_1);
+      if (v_0 || v_1)
+	SET_ASTATREG (vs, 1);
     }
   else if (P)
     {
-      SET_ASTATREG (v, v_i);
-      if (v_i)
-	SET_ASTATREG (vs, v_i);
+      SET_ASTATREG (v, v_0 | v_1);
+      if (v_0 || v_1)
+	SET_ASTATREG (vs, 1);
     }
 
   if ((w0 == 1 && op0 == 3) || (w1 == 1 && op1 == 3))
-- 
1.7.5.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]