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] Improved 64bit support for MIPS sim


Hello All,

I applied the appended patch, it generally improves 64bit support,
especially for 64bit floating point used in a 32bit CPU. Addresses
are still sign-extended 32bit values only.


Thiemo


2007-02-19  Thiemo Seufer  <ths@mips.com>
            Nigel Stephens  <nigel@mips.com>
            David Ung  <davidu@mips.com>

	* cp1.c (value_fpr): Don't inherit existing FPR_STATE for
	uninterpreted formats. If fmt is one of the uninterpreted types
	don't update the FPR_STATE. Handle fmt_uninterpreted_32 like
	fmt_word, and fmt_uninterpreted_64 like fmt_long.
	(store_fpr): When writing an invalid odd register, set the
	matching even register to fmt_unknown, not the following register.
	* interp.c (sim_open): If STATE_MEM_SIZE isn't set then set it to
	the the memory window at offset 0 set by --memory-size command
	line option.
	(sim_store_register): Handle storing 4 bytes to an 8 byte floating
	point register.
	(sim_fetch_register): Likewise for reading 4 bytes from an 8 byte
	register.
	(sim_monitor): When returning the memory size to the MIPS
	application, use the value in STATE_MEM_SIZE, not an arbitrary
	hardcoded value.
	(cop_lw): Don' mess around with FPR_STATE, just pass
	fmt_uninterpreted_32 to StoreFPR.
	(cop_sw): Similarly.
	(cop_ld): Pass fmt_uninterpreted_64 not fmt_uninterpreted.
	(cop_sd): Similarly.
	* mips.igen (not_word_value): Single version for mips32, mips64
	and mips16.


Index: head/sim/mips/cp1.c
===================================================================
RCS file: /cvs/src/src/sim/mips/cp1.c,v
retrieving revision 1.20
diff -u -p -r1.20 cp1.c
--- head/sim/mips/cp1.c	2 May 2003 22:17:21 -0000	1.20
+++ head/sim/mips/cp1.c	24 Nov 2006 11:12:18 -0000
@@ -111,10 +111,10 @@ value_fpr (sim_cpu *cpu,
   int err = 0;
 
   /* Treat unused register values, as fixed-point 64bit values.  */
-  if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
+  if (fmt == fmt_unknown)
     {
 #if 1
-      /* If request to read data as "uninterpreted", then use the current
+      /* If request to read data as "unknown", then use the current
 	 encoding:  */
       fmt = FPR_STATE[fpr];
 #else
@@ -123,20 +123,23 @@ value_fpr (sim_cpu *cpu,
     }
 
   /* For values not yet accessed, set to the desired format.  */
-  if (FPR_STATE[fpr] == fmt_uninterpreted)
+  if (fmt < fmt_uninterpreted) 
     {
-      FPR_STATE[fpr] = fmt;
+      if (FPR_STATE[fpr] == fmt_uninterpreted)
+	{
+	  FPR_STATE[fpr] = fmt;
 #ifdef DEBUG
-      printf ("DBG: Register %d was fmt_uninterpreted. Now %s\n", fpr,
-	      fpu_format_name (fmt));
+	  printf ("DBG: Register %d was fmt_uninterpreted. Now %s\n", fpr,
+		  fpu_format_name (fmt));
 #endif /* DEBUG */
-    }
-  if (fmt != FPR_STATE[fpr])
-    {
-      sim_io_eprintf (SD, "FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",
-		      fpr, fpu_format_name (FPR_STATE[fpr]),
-		      fpu_format_name (fmt), pr_addr (cia));
-      FPR_STATE[fpr] = fmt_unknown;
+	}
+      else if (fmt != FPR_STATE[fpr])
+	{
+	  sim_io_eprintf (SD, "FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",
+			  fpr, fpu_format_name (FPR_STATE[fpr]),
+			  fpu_format_name (fmt), pr_addr (cia));
+	  FPR_STATE[fpr] = fmt_unknown;
+	}
     }
 
   if (FPR_STATE[fpr] == fmt_unknown)
@@ -156,11 +159,13 @@ value_fpr (sim_cpu *cpu,
     {
       switch (fmt)
 	{
+	case fmt_uninterpreted_32:
 	case fmt_single:
 	case fmt_word:
 	  value = (FGR[fpr] & 0xFFFFFFFF);
 	  break;
 
+	case fmt_uninterpreted_64:
 	case fmt_uninterpreted:
 	case fmt_double:
 	case fmt_long:
@@ -177,11 +182,13 @@ value_fpr (sim_cpu *cpu,
     {
       switch (fmt)
 	{
+	case fmt_uninterpreted_32:
 	case fmt_single:
 	case fmt_word:
 	  value = (FGR[fpr] & 0xFFFFFFFF);
 	  break;
 
+	case fmt_uninterpreted_64:
 	case fmt_uninterpreted:
 	case fmt_double:
 	case fmt_long:
@@ -299,7 +306,7 @@ store_fpr (sim_cpu *cpu,
 	  else
 	    {
 	      FPR_STATE[fpr] = fmt_unknown;
-	      FPR_STATE[fpr + 1] = fmt_unknown;
+	      FPR_STATE[fpr ^ 1] = fmt_unknown;
 	      SignalException (ReservedInstruction, 0);
 	    }
 	  break;
Index: head/sim/mips/interp.c
===================================================================
RCS file: /cvs/src/src/sim/mips/interp.c,v
retrieving revision 1.19
diff -u -p -r1.19 interp.c
--- head/sim/mips/interp.c	12 May 2004 01:42:33 -0000	1.19
+++ head/sim/mips/interp.c	24 Nov 2006 11:12:18 -0000
@@ -131,6 +131,9 @@ static void ColdReset PARAMS((SIM_DESC s
 
 /* Note that the monitor code essentially assumes this layout of memory.
    If you change these, change the monitor code, too.  */
+/* FIXME Currently addresses are truncated to 32-bits, see
+   mips/sim-main.c:address_translation(). If that changes, then these
+   values will need to be extended, and tested for more carefully. */
 #define K0BASE  (0x80000000)
 #define K0SIZE  (0x20000000)
 #define K1BASE  (0xA0000000)
@@ -365,17 +368,67 @@ sim_open (kind, cb, abfd, argv)
   if (board == NULL)
     {
       /* Allocate core managed memory */
-      
+      sim_memopt *entry, *match = NULL;
+      address_word mem_size = 0;
+      int mapped = 0;
 
       /* For compatibility with the old code - under this (at level one)
 	 are the kernel spaces K0 & K1.  Both of these map to a single
 	 smaller sub region */
       sim_do_command(sd," memory region 0x7fff8000,0x8000") ; /* MTZ- 32 k stack */
-      sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
-		       K1BASE, K0SIZE,
-		       MEM_SIZE, /* actual size */
-		       K0BASE);
-      
+
+      /* Look for largest memory region defined on command-line at
+	 phys address 0. */
+#ifdef SIM_HAVE_FLATMEM
+      mem_size = STATE_MEM_SIZE (sd);
+#endif
+      for (entry = STATE_MEMOPT (sd); entry != NULL; entry = entry->next)
+	{
+	  /* If we find an entry at address 0, then we will end up
+	     allocating a new buffer in the "memory alias" command
+	     below. The region at address 0 will be deleted. */
+	  address_word size = (entry->modulo != 0
+			       ? entry->modulo : entry->nr_bytes);
+	  if (entry->addr == 0
+	      && (!match || entry->level < match->level))
+	    match = entry;
+	  else if (entry->addr == K0BASE || entry->addr == K1BASE)
+	    mapped = 1;
+	  else
+	    {
+	      sim_memopt *alias;
+	      for (alias = entry->alias; alias != NULL; alias = alias->next)
+		{
+		  if (alias->addr == 0
+		      && (!match || entry->level < match->level))
+		    match = entry;
+		  else if (alias->addr == K0BASE || alias->addr == K1BASE)
+		    mapped = 1;
+		}
+	    }
+	}
+
+      if (!mapped)
+	{
+	  if (match)
+	    {
+	      /* Get existing memory region size. */
+	      mem_size = (match->modulo != 0
+			  ? match->modulo : match->nr_bytes);
+	      /* Delete old region. */
+	      sim_do_commandf (sd, "memory delete %d:0x%lx@%d",
+			       match->space, match->addr, match->level);
+	    }	      
+	  else if (mem_size == 0)
+	    mem_size = MEM_SIZE;
+	  /* Limit to KSEG1 size (512MB) */
+	  if (mem_size > K1SIZE)
+	    mem_size = K1SIZE;
+	  /* memory alias K1BASE@1,K1SIZE%MEMSIZE,K0BASE */
+	  sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
+			   K1BASE, K1SIZE, (long)mem_size, K0BASE);
+	}
+
       device_init(sd);
     }
   else if (board != NULL
@@ -868,8 +921,16 @@ sim_store_register (sd,rn,memory,length)
 	}
       else
 	{
-	  cpu->fgr[rn - FGR_BASE] = T2H_8 (*(unsigned64*)memory);
-	  return 8;
+          if (length == 8)
+	    {
+	      cpu->fgr[rn - FGR_BASE] = T2H_8 (*(unsigned64*)memory);
+	      return 8;
+	    }
+	  else
+	    {
+	      cpu->fgr[rn - FGR_BASE] = T2H_4 (*(unsigned32*)memory);
+	      return 4;
+	    }
 	}
     }
 
@@ -889,8 +950,16 @@ sim_store_register (sd,rn,memory,length)
     }
   else
     {
-      cpu->registers[rn] = T2H_8 (*(unsigned64*)memory);
-      return 8;
+      if (length == 8)
+	{
+	  cpu->registers[rn] = T2H_8 (*(unsigned64*)memory);
+	  return 8;
+	}
+      else
+	{
+	  cpu->registers[rn] = (signed32) T2H_4(*(unsigned32*)memory);
+	  return 4;
+	}
     }
 
   return 0;
@@ -939,8 +1008,16 @@ sim_fetch_register (sd,rn,memory,length)
 	}
       else
 	{
-	  *(unsigned64*)memory = H2T_8 (cpu->fgr[rn - FGR_BASE]);
-	  return 8;
+	  if (length == 8)
+	    {
+	      *(unsigned64*)memory = H2T_8 (cpu->fgr[rn - FGR_BASE]);
+	      return 8;
+	    }
+	  else
+	    {
+	      *(unsigned32*)memory = H2T_4 ((unsigned32)(cpu->fgr[rn - FGR_BASE]));
+	      return 4;
+	    }
 	}
     }
 
@@ -960,8 +1037,17 @@ sim_fetch_register (sd,rn,memory,length)
     }
   else
     {
-      *(unsigned64*)memory = H2T_8 ((unsigned64)(cpu->registers[rn]));
-      return 8;
+      if (length == 8)
+	{
+	  *(unsigned64*)memory =
+	    H2T_8 ((unsigned64) (cpu->registers[rn]));
+	  return 8;
+	}
+      else
+	{
+	  *(unsigned32*)memory = H2T_4 ((unsigned32)(cpu->registers[rn]));
+	  return 4;
+	}
     }
 
   return 0;
@@ -1235,8 +1325,39 @@ sim_monitor (SIM_DESC sd,
       /*      [A0 + 4] = instruction cache size */
       /*      [A0 + 8] = data cache size */
       {
-	unsigned_4 value = MEM_SIZE /* FIXME STATE_MEM_SIZE (sd) */;
+	unsigned_4 value;
 	unsigned_4 zero = 0;
+	address_word mem_size;
+	sim_memopt *entry, *match = NULL;
+
+	/* Search for memory region mapped to KSEG0 or KSEG1. */
+	for (entry = STATE_MEMOPT (sd); 
+	     entry != NULL;
+	     entry = entry->next)
+	  {
+	    if ((entry->addr == K0BASE || entry->addr == K1BASE)
+		&& (!match || entry->level < match->level))
+	      match = entry;
+	    else
+	      {
+		sim_memopt *alias;
+		for (alias = entry->alias; 
+		     alias != NULL;
+		     alias = alias->next)
+		  if ((alias->addr == K0BASE || alias->addr == K1BASE)
+		      && (!match || entry->level < match->level))
+		    match = entry;
+	      }
+	  }
+
+	/* Get region size, limit to KSEG1 size (512MB). */
+	SIM_ASSERT (match != NULL);
+	mem_size = (match->modulo != 0
+		    ? match->modulo : match->nr_bytes);
+	if (mem_size > K1SIZE)
+	  mem_size = K1SIZE;
+
+	value = mem_size;
 	H2T (value);
 	sim_write (sd, A0 + 0, (char *)&value, 4);
 	sim_write (sd, A0 + 4, (char *)&zero, 4);
@@ -1924,8 +2059,7 @@ cop_lw (SIM_DESC sd,
 #ifdef DEBUG
 	  printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword,pr_addr(memword));
 #endif
-	  StoreFPR(coproc_reg,fmt_word,(uword64)memword);
-	  FPR_STATE[coproc_reg] = fmt_uninterpreted;
+	  StoreFPR(coproc_reg,fmt_uninterpreted_32,(uword64)memword);
 	  break;
 	}
 
@@ -1956,7 +2090,7 @@ cop_ld (SIM_DESC sd,
     case 1:
       if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
 	{
-	  StoreFPR(coproc_reg,fmt_uninterpreted,memword);
+	  StoreFPR(coproc_reg,fmt_uninterpreted_64,memword);
 	  break;
 	}
 
@@ -1987,11 +2121,7 @@ cop_sw (SIM_DESC sd,
     case 1:
       if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
 	{
-	  FP_formats hold;
-	  hold = FPR_STATE[coproc_reg];
-	  FPR_STATE[coproc_reg] = fmt_word;
-	  value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted);
-	  FPR_STATE[coproc_reg] = hold;
+	  value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted_32);
 	  break;
 	}
 
@@ -2018,7 +2148,7 @@ cop_sd (SIM_DESC sd,
     case 1:
       if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
 	{
-	  value = ValueFPR(coproc_reg,fmt_uninterpreted);
+	  value = ValueFPR(coproc_reg,fmt_uninterpreted_64);
 	  break;
 	}
 
Index: head/sim/mips/mips.igen
===================================================================
RCS file: /cvs/src/src/sim/mips/mips.igen,v
retrieving revision 1.61
diff -u -p -r1.61 mips.igen
--- head/sim/mips/mips.igen	29 Aug 2006 12:45:26 -0000	1.61
+++ head/sim/mips/mips.igen	24 Nov 2006 11:12:18 -0000
@@ -176,29 +176,18 @@
 *vr4100:
 *vr5000:
 *r3900:
-{
-  /* For historical simulator compatibility (until documentation is
-     found that makes these operations unpredictable on some of these
-     architectures), this check never returns true.  */
-  return 0;
-}
-
-:function:::int:not_word_value:unsigned_word value
 *mips32:
 *mips32r2:
-{
-  /* On MIPS32, since registers are 32-bits, there's no check to be done.  */
-  return 0;
-}
-
-:function:::int:not_word_value:unsigned_word value
 *mips64:
 *mips64r2:
 {
-  return ((value >> 32) != (value & 0x80000000 ? 0xFFFFFFFF : 0));
+#if WITH_TARGET_WORD_BITSIZE == 64
+  return value != (((value & 0xffffffff) ^ 0x80000000) - 0x80000000);
+#else
+  return 0;
+#endif
 }
 
-
 // Helper:
 //
 // Handle UNPREDICTABLE operation behaviour.  The goal here is to prevent


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