This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[mt patch] Add coprocessor array
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: kevinb at redhat dot com
- Cc: gdb-patches at sources dot redhat dot com
- Date: Wed, 21 Dec 2005 11:25:08 +0000
- Subject: [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;
}
}