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]

[mt patch] Add coprocessor array


The MT architecture has an array of coprocessors, whose registers are accessible via a window of real registers. A control register determines which coprocessor that window reveals. This patch adds knowledge of that mapping to gdb, making the entire coprocessor array visible, albeit with somewhat awkward names (it is a pity gdb's not set up to deal with the register set as some kind of aggregate object). This allows an unmodified eclipse to access these registers.

ok?

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2005-12-21  Nathan Sidwell  <nathan@codesourcery.com>

	* mt-tdep.c (enum mt_gdb_regnums): Add MT_COPRO_PSEUDOREG_ARRAY,
	MT_COPRO_PSEUDOREG_DIM_1, MT_COPRO_PSEUDOREG_DIM_2,
	MT_COPRO_PSEUDOREG_REGS members.  Adjust MT_NUM_PSEUDO_REGS.
	(mt_register_name): Lazily synthesize name for coprocessor pseudo
	array registers.
	(mt_copro_register_type): New. Broken out of ...
	(mt_register_type): ... here.  Use it.  Deal with coprocessor
	pseudo array.
	(mt_select_coprocessor): New.
	(mt_pseudo_register_read, mt_pseudo_register_write): Deal with
	coprocessor pseudo array.

Index: mt-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mt-tdep.c,v
retrieving revision 1.2
diff -c -3 -p -r1.2 mt-tdep.c
*** mt-tdep.c	16 Dec 2005 10:23:09 -0000	1.2
--- mt-tdep.c	21 Dec 2005 11:11:18 -0000
*************** enum mt_gdb_regnums
*** 116,124 ****
    /* Pseudo-registers.  */
    MT_COPRO_PSEUDOREG_REGNUM = MT_NUM_REGS,
    MT_MAC_PSEUDOREG_REGNUM,
  
    /* Two pseudo-regs ('coprocessor' and 'mac').  */
!   MT_NUM_PSEUDO_REGS = 2
  };
  
  /* Return name of register number specified by REGNUM.  */
--- 116,131 ----
    /* Pseudo-registers.  */
    MT_COPRO_PSEUDOREG_REGNUM = MT_NUM_REGS,
    MT_MAC_PSEUDOREG_REGNUM,
+   MT_COPRO_PSEUDOREG_ARRAY,
+ 
+   MT_COPRO_PSEUDOREG_DIM_1 = 2,
+   MT_COPRO_PSEUDOREG_DIM_2 = 8,
+   MT_COPRO_PSEUDOREG_REGS = 32,
  
    /* Two pseudo-regs ('coprocessor' and 'mac').  */
!   MT_NUM_PSEUDO_REGS = 2 + (MT_COPRO_PSEUDOREG_REGS
! 			    * MT_COPRO_PSEUDOREG_DIM_1
! 			    * MT_COPRO_PSEUDOREG_DIM_2)
  };
  
  /* Return name of register number specified by REGNUM.  */
*************** mt_register_name (int regnum)
*** 140,148 ****
      /* Pseudo-registers.  */
      "coprocessor", "MAC"
    };
  
!   gdb_assert (regnum >= 0 && regnum < ARRAY_SIZE (register_names));
!   return register_names[regnum];
  }
  
  /* Given ARCH and a register number specified by REGNUM, return the
--- 147,235 ----
      /* Pseudo-registers.  */
      "coprocessor", "MAC"
    };
+   static const char *array_names[MT_COPRO_PSEUDOREG_REGS
+ 				 * MT_COPRO_PSEUDOREG_DIM_1
+ 				 * MT_COPRO_PSEUDOREG_DIM_2];
+ 
+   if (regnum < 0)
+     return "";
+   if (regnum < ARRAY_SIZE (register_names))
+     return register_names[regnum];
+   if (array_names[regnum - MT_COPRO_PSEUDOREG_ARRAY])
+     return array_names[regnum - MT_COPRO_PSEUDOREG_ARRAY];
+   
+   {
+     char *name;
+     const char *stub;
+     unsigned dim_1;
+     unsigned dim_2;
+     unsigned index;
+     
+     regnum -= MT_COPRO_PSEUDOREG_ARRAY;
+     index = regnum % MT_COPRO_PSEUDOREG_REGS;
+     dim_2 = (regnum / MT_COPRO_PSEUDOREG_REGS) % MT_COPRO_PSEUDOREG_DIM_2;
+     dim_1 = ((regnum / MT_COPRO_PSEUDOREG_REGS / MT_COPRO_PSEUDOREG_DIM_2)
+ 	     %  MT_COPRO_PSEUDOREG_DIM_1);
+     
+     if (index == MT_COPRO_PSEUDOREG_REGS - 1)
+       stub = register_names[MT_MAC_PSEUDOREG_REGNUM];
+     else if (index > MT_QCHANNEL_REGNUM - MT_CPR0_REGNUM)
+       stub = "";
+     else
+       stub = register_names[index + MT_CPR0_REGNUM];
+     if (!*stub)
+       {
+ 	array_names[regnum] = stub;
+ 	return stub;
+       }
+     name = xmalloc (30);
+     sprintf (name, "copro_%d_%d_%s", dim_1, dim_2, stub);
+     array_names[regnum] = name;
+     return name;
+   }
+ }
  
! /* Return the type of a coprocessor register.  */
! 
! static struct type *
! mt_copro_register_type (struct gdbarch *arch, int regnum)
! {
!   switch (regnum)
!     {
!     case MT_INT_ENABLE_REGNUM:
!     case MT_ICHANNEL_REGNUM:
!     case MT_QCHANNEL_REGNUM:
!     case MT_ISCRAMB_REGNUM:
!     case MT_QSCRAMB_REGNUM:
!       return builtin_type_int32;
!     case MT_BYPA_REGNUM:
!     case MT_BYPB_REGNUM:
!     case MT_BYPC_REGNUM:
!     case MT_Z1_REGNUM:
!     case MT_Z2_REGNUM:
!     case MT_OUT_REGNUM:
!       return builtin_type_int16;
!     case MT_EXMAC_REGNUM:
!     case MT_MAC_REGNUM:
!       return builtin_type_uint32;
!     case MT_CONTEXT_REGNUM:
!       return builtin_type_long_long;
!     case MT_FLAG_REGNUM:
!       return builtin_type_unsigned_char;
!     default:
!       if (regnum >= MT_CPR0_REGNUM && regnum <= MT_CPR15_REGNUM)
! 	return builtin_type_int16;
!       else if (regnum == MT_CPR0_REGNUM + MT_COPRO_PSEUDOREG_REGS - 1)
! 	{
! 	  if (gdbarch_bfd_arch_info (arch)->mach == bfd_mach_mrisc2
! 	      || gdbarch_bfd_arch_info (arch)->mach == bfd_mach_ms2)
! 	    return builtin_type_uint64;
! 	  else
! 	    return builtin_type_uint32;
! 	}
!       else
! 	return builtin_type_uint32;
!     }
  }
  
  /* Given ARCH and a register number specified by REGNUM, return the
*************** mt_register_type (struct gdbarch *arch, 
*** 176,215 ****
  	case MT_SP_REGNUM:
  	case MT_FP_REGNUM:
  	  return void_ptr;
- 	case MT_INT_ENABLE_REGNUM:
- 	case MT_ICHANNEL_REGNUM:
- 	case MT_QCHANNEL_REGNUM:
- 	case MT_ISCRAMB_REGNUM:
- 	case MT_QSCRAMB_REGNUM:
- 	  return builtin_type_int32;
- 	case MT_EXMAC_REGNUM:
- 	case MT_MAC_REGNUM:
- 	  return builtin_type_uint32;
- 	case MT_BYPA_REGNUM:
- 	case MT_BYPB_REGNUM:
- 	case MT_BYPC_REGNUM:
- 	case MT_Z1_REGNUM:
- 	case MT_Z2_REGNUM:
- 	case MT_OUT_REGNUM:
- 	  return builtin_type_int16;
- 	case MT_CONTEXT_REGNUM:
- 	  return builtin_type_long_long;
  	case MT_COPRO_REGNUM:
  	case MT_COPRO_PSEUDOREG_REGNUM:
  	  return copro_type;
  	case MT_MAC_PSEUDOREG_REGNUM:
! 	  if (gdbarch_bfd_arch_info (arch)->mach == bfd_mach_mrisc2
! 	      || gdbarch_bfd_arch_info (arch)->mach == bfd_mach_ms2)
! 	    return builtin_type_uint64;
! 	  else
! 	    return builtin_type_uint32;
! 	case MT_FLAG_REGNUM:
! 	  return builtin_type_unsigned_char;
  	default:
  	  if (regnum >= MT_R0_REGNUM && regnum <= MT_R15_REGNUM)
  	    return builtin_type_int32;
! 	  else if (regnum >= MT_CPR0_REGNUM && regnum <= MT_CPR15_REGNUM)
! 	    return builtin_type_int16;
  	}
      }
    internal_error (__FILE__, __LINE__,
--- 263,287 ----
  	case MT_SP_REGNUM:
  	case MT_FP_REGNUM:
  	  return void_ptr;
  	case MT_COPRO_REGNUM:
  	case MT_COPRO_PSEUDOREG_REGNUM:
  	  return copro_type;
  	case MT_MAC_PSEUDOREG_REGNUM:
! 	  return mt_copro_register_type (arch,
! 					 MT_CPR0_REGNUM
! 					 + MT_COPRO_PSEUDOREG_REGS - 1);
  	default:
  	  if (regnum >= MT_R0_REGNUM && regnum <= MT_R15_REGNUM)
  	    return builtin_type_int32;
! 	  else if (regnum < MT_COPRO_PSEUDOREG_ARRAY)
! 	    return mt_copro_register_type (arch, regnum);
! 	  else
! 	    {
! 	      regnum -= MT_COPRO_PSEUDOREG_ARRAY;
! 	      regnum %= MT_COPRO_PSEUDOREG_REGS;
! 	      regnum += MT_CPR0_REGNUM;
! 	      return mt_copro_register_type (arch, regnum);
! 	    }
  	}
      }
    internal_error (__FILE__, __LINE__,
*************** mt_breakpoint_from_pc (CORE_ADDR *bp_add
*** 379,392 ****
    return ms1_breakpoint;
  }
  
  /* Fetch the pseudo registers:
  
!    There are two pseudo-registers:
     1) The 'coprocessor' pseudo-register (which mirrors the 
     "real" coprocessor register sent by the target), and
     2) The 'MAC' pseudo-register (which represents the union
     of the original 32 bit target MAC register and the new
!    8-bit extended-MAC register).  */
  
  static void
  mt_pseudo_register_read (struct gdbarch *gdbarch,
--- 451,503 ----
    return ms1_breakpoint;
  }
  
+ /* Select the correct coprocessor register bank.  Return the pseudo
+    regnum we really want to read.  */
+ 
+ static int
+ mt_select_coprocessor (struct gdbarch *gdbarch,
+ 			struct regcache *regcache, int regno)
+ {
+   unsigned index, base;
+   gdb_byte copro[4];
+ 
+   /* Get the copro pseudo regnum. */
+   regcache_raw_read (regcache, MT_COPRO_REGNUM, copro);
+   base = (extract_signed_integer (&copro[0], 2) * MT_COPRO_PSEUDOREG_DIM_2
+ 	  + extract_signed_integer (&copro[2], 2));
+ 
+   regno -= MT_COPRO_PSEUDOREG_ARRAY;
+   index = regno % MT_COPRO_PSEUDOREG_REGS;
+   regno /= MT_COPRO_PSEUDOREG_REGS;
+   if (base != regno)
+     {
+       /* Select the correct coprocessor register bank.  Invalidate the
+ 	 coprocessor register cache.  */
+       unsigned ix;
+ 
+       store_signed_integer (&copro[0], 2, regno / MT_COPRO_PSEUDOREG_DIM_2);
+       store_signed_integer (&copro[2], 2, regno % MT_COPRO_PSEUDOREG_DIM_2);
+       regcache_raw_write (regcache, MT_COPRO_REGNUM, copro);
+       
+       /* We must flush the cache, as it is now invalid.  */
+       for (ix = MT_NUM_CPU_REGS; ix != MT_NUM_REGS; ix++)
+ 	set_register_cached (ix, 0);
+     }
+   
+   return index;
+ }
+ 
  /* Fetch the pseudo registers:
  
!    There are two regular pseudo-registers:
     1) The 'coprocessor' pseudo-register (which mirrors the 
     "real" coprocessor register sent by the target), and
     2) The 'MAC' pseudo-register (which represents the union
     of the original 32 bit target MAC register and the new
!    8-bit extended-MAC register).
! 
!    Additionally there is an array of coprocessor registers which track
!    the coprocessor registers for each coprocessor.  */
  
  static void
  mt_pseudo_register_read (struct gdbarch *gdbarch,
*************** mt_pseudo_register_read (struct gdbarch 
*** 416,423 ****
  	regcache_raw_read (regcache, MT_MAC_REGNUM, buf);
        break;
      default:
!       internal_error (__FILE__, __LINE__,
! 		      _("mt_pseudo_register_read: bad reg # (%d)"), regno);
        break;
      }
  }
--- 527,541 ----
  	regcache_raw_read (regcache, MT_MAC_REGNUM, buf);
        break;
      default:
!       {
! 	unsigned index = mt_select_coprocessor (gdbarch, regcache, regno);
! 	
! 	if (index == MT_COPRO_PSEUDOREG_REGS - 1)
! 	  mt_pseudo_register_read (gdbarch, regcache,
! 				   MT_COPRO_PSEUDOREG_REGNUM, buf);
! 	else if (index < MT_NUM_REGS - MT_CPR0_REGNUM)
! 	  regcache_raw_read (regcache, index + MT_CPR0_REGNUM, buf);
!       }
        break;
      }
  }
*************** mt_pseudo_register_write (struct gdbarch
*** 463,470 ****
  	regcache_raw_write (regcache, MT_MAC_REGNUM, buf);
        break;
      default:
!       internal_error (__FILE__, __LINE__,
! 		      _("mt_pseudo_register_write: bad reg # (%d)"), regno);
        break;
      }
  }
--- 581,595 ----
  	regcache_raw_write (regcache, MT_MAC_REGNUM, buf);
        break;
      default:
!       {
! 	unsigned index = mt_select_coprocessor (gdbarch, regcache, regno);
! 	
! 	if (index == MT_COPRO_PSEUDOREG_REGS - 1)
! 	  mt_pseudo_register_write (gdbarch, regcache,
! 				    MT_COPRO_PSEUDOREG_REGNUM, buf);
! 	else if (index < MT_NUM_REGS - MT_CPR0_REGNUM)
! 	  regcache_raw_write (regcache, index + MT_CPR0_REGNUM, buf);
!       }
        break;
      }
  }

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