This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[patch,rfc] builtin regs -> user regs
- From: Andrew Cagney <ac131313 at redhat dot com>
- To: gdb-patches at sources dot redhat dot com
- Date: Sun, 29 Jun 2003 11:15:35 -0400
- Subject: [patch,rfc] builtin regs -> user regs
Hello,
Ref: Three register layers
http://sources.redhat.com/ml/gdb/2003-06/msg00437.html
This patch replaces the builtin registers with user [visible] per-frame
registers.
The builtin registers were global - always present regardless of the
architecture. These new user [visible] registers support both global,
and per-architecture registers.
As with the above post, these registers live on top of the frame vis:
user
|
cooked/frame
|
raw
and this makes it possible to construct user visible registers using
per-frame register values. In the case of the MIPS, the 64 bit $fpr0
would be the concatenation of the two 32 bit registers: $fgr0 and $fgr1.
Please note though that the way registers are read/written needs further
refinement (I left it as is for the moment). I suspect, for instance,
that currently register writes don't work at all.
I'm also not comfortable with using `builtin' for the registers that
apply to all architectures. Perhaphs:
user_reg_add_all
user_reg_add_global
are better. Thougts?
comments?
Andrew
(no this isn't for the 6.0 branch)
2003-06-29 Andrew Cagney <cagney@redhat.com>
* expprint.c: Include "user-regs.h" instead of "frame.h".
(print_subexp): Use user_reg_map_regnum_to_name, instead of
frame_map_regnum_to_name.
* frame.c: Include "user-regs.h" instead of "builtin-regs.h".
(frame_map_name_to_regnum): Simplify, call
user_reg_map_name_to_regnum.
(frame_map_regnum_to_name): Simplify, call
user_reg_map_regnum_to_name.
(frame_register_unwind): Update.
* std-regs.c: Include "user-regs.h" instead of "builtin-regs.h".
(_initialize_frame_reg): Call user_reg_add_builtin.
* findvar.c: Include "user-regs.h" instead of "builtin-regs.h".
(value_of_register): Use value_of_user_reg.
* eval.c (evaluate_subexp_standard): Update.
* parse.c (write_dollar_variable): Update.
* d10v-tdep.c (d10v_print_registers_info): Update.
* infcmd.c (registers_info): Update.
* Makefile.in (SFILES): Delete "builtin-regs.c", add "user-regs.c".
(builtin_regs_h): Delete macro.
(user_regs_h): Define.
(COMMON_OBS): Delete "builtin-regs.o", add "user-regs.o".
(builtin-regs.o): Delete target.
(user-regs.o): Specify dependencies.
(expprint.o): Update dependencies.
(findvar.o): Update dependencies.
(frame.o): Update dependencies.
(std-regs.o): Update dependencies.
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.411
diff -u -r1.411 Makefile.in
--- Makefile.in 28 Jun 2003 16:19:05 -0000 1.411
+++ Makefile.in 29 Jun 2003 15:01:31 -0000
@@ -510,7 +510,7 @@
SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
ax-general.c ax-gdb.c \
- bcache.c block.c blockframe.c breakpoint.c buildsym.c builtin-regs.c \
+ bcache.c block.c blockframe.c breakpoint.c buildsym.c \
c-exp.y c-lang.c c-typeprint.c c-valprint.c \
charset.c cli-out.c coffread.c coff-pe-read.c \
complaints.c completer.c corefile.c \
@@ -554,6 +554,7 @@
tui/tuiStack.c tui/tuiStack.h tui/tuiWin.c tui/tuiWin.h \
tui/tui-file.h tui/tui-file.c tui/tui-out.c tui/tui-hooks.c \
ui-out.c utils.c ui-file.h ui-file.c \
+ user-regs.c \
valarith.c valops.c valprint.c values.c varobj.c \
wrapper.c
@@ -618,7 +619,6 @@
block_h = block.h
breakpoint_h = breakpoint.h $(frame_h) $(value_h) $(gdb_events_h)
buildsym_h = buildsym.h
-builtin_regs_h = builtin-regs.h
c_lang_h = c-lang.h $(value_h) $(macroexp_h)
call_cmds_h = call-cmds.h
ch_lang_h = ch-lang.h
@@ -749,6 +749,7 @@
typeprint_h = typeprint.h
ui_file_h = ui-file.h
ui_out_h = ui-out.h
+user_regs_h = user-regs.h
valprint_h = valprint.h
value_h = value.h $(doublest_h) $(frame_h) $(symtab_h) $(gdbtypes_h) $(expression_h)
varobj_h = varobj.h $(symtab_h) $(gdbtypes_h)
@@ -862,7 +863,7 @@
event-loop.o event-top.o inf-loop.o completer.o \
gdbarch.o arch-utils.o gdbtypes.o osabi.o copying.o $(DEPFILES) \
memattr.o mem-break.o target.o parse.o language.o $(YYOBJ) buildsym.o \
- builtin-regs.o std-regs.o \
+ std-regs.o \
signals.o \
kod.o kod-cisco.o \
gdb-events.o \
@@ -882,6 +883,7 @@
c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o \
nlmread.o serial.o mdebugread.o top.o utils.o \
ui-file.o \
+ user-regs.o \
frame.o frame-unwind.o doublest.o \
frame-base.o \
gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o \
@@ -1597,8 +1599,6 @@
$(complaints_h) $(gdb_string_h) $(expression_h) $(language_h) \
$(bcache_h) $(filenames_h) $(macrotab_h) $(demangle_h) $(buildsym_h) \
$(stabsread_h) $(block_h) $(cp_support_h) $(dictionary_h)
-builtin-regs.o: builtin-regs.c $(defs_h) $(builtin_regs_h) $(gdbtypes_h) \
- $(gdb_string_h) $(gdb_assert_h)
c-lang.o: c-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
$(parser_defs_h) $(language_h) $(c_lang_h) $(valprint_h) \
$(macroscope_h) $(gdb_assert_h) $(charset_h) $(gdb_string_h) \
@@ -1728,8 +1728,8 @@
$(gdb_string_h) $(gdbcore_h) $(gdb_stat_h) $(xcoffsolib_h) \
$(readline_h)
expprint.o: expprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
- $(value_h) $(language_h) $(parser_defs_h) $(target_h) $(gdb_string_h) \
- $(block_h)
+ $(value_h) $(language_h) $(parser_defs_h) $(user_regs_h) $(target_h) \
+ $(gdb_string_h) $(block_h)
f-lang.o: f-lang.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(expression_h) $(parser_defs_h) $(language_h) $(f_lang_h) \
$(valprint_h) $(value_h)
@@ -1744,12 +1744,12 @@
findvar.o: findvar.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(frame_h) \
$(value_h) $(gdbcore_h) $(inferior_h) $(target_h) $(gdb_string_h) \
$(gdb_assert_h) $(floatformat_h) $(symfile_h) $(regcache_h) \
- $(builtin_regs_h) $(block_h)
+ $(user_regs_h) $(block_h)
fork-child.o: fork-child.c $(defs_h) $(gdb_string_h) $(frame_h) \
$(inferior_h) $(target_h) $(gdb_wait_h) $(gdb_vfork_h) $(gdbcore_h) \
$(terminal_h) $(gdbthread_h) $(command_h)
frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \
- $(regcache_h) $(gdb_assert_h) $(gdb_string_h) $(builtin_regs_h) \
+ $(regcache_h) $(gdb_assert_h) $(gdb_string_h) $(user_regs_h) \
$(gdb_obstack_h) $(dummy_frame_h) $(sentinel_frame_h) $(gdbcore_h) \
$(annotate_h) $(language_h) $(frame_unwind_h) $(frame_base_h) \
$(command_h) $(gdbcmd_h)
@@ -2288,7 +2288,7 @@
$(gdb_assert_h) $(dictionary_h)
standalone.o: standalone.c $(gdb_stat_h) $(defs_h) $(symtab_h) $(frame_h) \
$(inferior_h) $(gdb_wait_h)
-std-regs.o: std-regs.c $(defs_h) $(builtin_regs_h) $(frame_h) $(gdbtypes_h) \
+std-regs.o: std-regs.c $(defs_h) $(user_regs_h) $(frame_h) $(gdbtypes_h) \
$(value_h) $(gdb_string_h)
stop-gdb.o: stop-gdb.c $(defs_h)
sun3-nat.o: sun3-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(regcache_h)
@@ -2342,6 +2342,8 @@
ui-file.o: ui-file.c $(defs_h) $(ui_file_h) $(gdb_string_h)
ui-out.o: ui-out.c $(defs_h) $(gdb_string_h) $(expression_h) $(language_h) \
$(ui_out_h) $(gdb_assert_h)
+user-regs.o: user-regs.c $(defs_h) $(user_regs_h) $(gdbtypes_h) \
+ $(gdb_string_h) $(gdb_assert_h) $(frame_h)
utils.o: utils.c $(config_h) $(defs_h) $(gdb_assert_h) $(gdb_string_h) \
$(event_top_h) $(gdbcmd_h) $(serial_h) $(bfd_h) $(target_h) \
$(demangle_h) $(expression_h) $(language_h) $(annotate_h) \
Index: builtin-regs.c
===================================================================
RCS file: builtin-regs.c
diff -N builtin-regs.c
--- builtin-regs.c 25 Sep 2002 20:30:37 -0000 1.3
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,86 +0,0 @@
-/* Builtin registers, for GDB, the GNU debugger.
-
- Copyright 2002 Free Software Foundation, Inc.
-
- Contributed by Red Hat.
-
- This file is part of GDB.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-#include "defs.h"
-#include "builtin-regs.h"
-#include "gdbtypes.h"
-#include "gdb_string.h"
-#include "gdb_assert.h"
-
-/* Implement builtin register types. Builtin registers have regnum's
- that live above of the range [0 .. NUM_REGS + NUM_PSEUDO_REGS)
- (which is controlled by the target). The target should never see a
- builtin register's regnum value. */
-
-/* An array of builtin registers. Always append, never delete. By
- doing this, the relative regnum (offset from NUM_REGS +
- NUM_PSEUDO_REGS) assigned to each builtin register never changes. */
-
-struct builtin_reg
-{
- const char *name;
- struct value *(*value) (struct frame_info * frame);
-};
-
-static struct builtin_reg *builtin_regs;
-int nr_builtin_regs;
-
-void
-add_builtin_reg (const char *name, struct value *(*value) (struct frame_info * frame))
-{
- nr_builtin_regs++;
- builtin_regs = xrealloc (builtin_regs,
- nr_builtin_regs * sizeof (builtin_regs[0]));
- builtin_regs[nr_builtin_regs - 1].name = name;
- builtin_regs[nr_builtin_regs - 1].value = value;
-}
-
-int
-builtin_reg_map_name_to_regnum (const char *name, int len)
-{
- int reg;
- for (reg = 0; reg < nr_builtin_regs; reg++)
- {
- if (len == strlen (builtin_regs[reg].name)
- && strncmp (builtin_regs[reg].name, name, len) == 0)
- return NUM_REGS + NUM_PSEUDO_REGS + reg;
- }
- return -1;
-}
-
-const char *
-builtin_reg_map_regnum_to_name (int regnum)
-{
- int reg = regnum - (NUM_REGS + NUM_PSEUDO_REGS);
- if (reg < 0 || reg >= nr_builtin_regs)
- return NULL;
- return builtin_regs[reg].name;
-}
-
-struct value *
-value_of_builtin_reg (int regnum, struct frame_info *frame)
-{
- int reg = regnum - (NUM_REGS + NUM_PSEUDO_REGS);
- gdb_assert (reg >= 0 && reg < nr_builtin_regs);
- return builtin_regs[reg].value (frame);
-}
Index: builtin-regs.h
===================================================================
RCS file: builtin-regs.h
diff -N builtin-regs.h
--- builtin-regs.h 12 Apr 2003 17:41:25 -0000 1.3
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,39 +0,0 @@
-/* Builtin registers, for GDB, the GNU debugger.
-
- Copyright 2002 Free Software Foundation, Inc.
-
- Contributed by Red Hat.
-
- This file is part of GDB.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-#ifndef BUILTIN_REGS_H
-#define BUILTIN_REGS_H
-
-struct frame_info;
-
-extern int builtin_reg_map_name_to_regnum (const char *str, int len);
-
-extern const char *builtin_reg_map_regnum_to_name (int regnum);
-
-extern struct value *value_of_builtin_reg (int regnum,
- struct frame_info *frame);
-
-extern void add_builtin_reg (const char *name,
- struct value *(value) (struct frame_info * frame));
-
-#endif
Index: d10v-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/d10v-tdep.c,v
retrieving revision 1.125
diff -u -r1.125 d10v-tdep.c
--- d10v-tdep.c 13 Jun 2003 20:37:27 -0000 1.125
+++ d10v-tdep.c 29 Jun 2003 15:01:31 -0000
@@ -797,9 +797,9 @@
ULONGEST pc, psw, rpt_s, rpt_e, rpt_c;
frame_read_unsigned_register (frame, D10V_PC_REGNUM, &pc);
frame_read_unsigned_register (frame, PSW_REGNUM, &psw);
- frame_read_unsigned_register (frame, frame_map_name_to_regnum ("rpt_s", -1), &rpt_s);
- frame_read_unsigned_register (frame, frame_map_name_to_regnum ("rpt_e", -1), &rpt_e);
- frame_read_unsigned_register (frame, frame_map_name_to_regnum ("rpt_c", -1), &rpt_c);
+ frame_read_unsigned_register (frame, frame_map_name_to_regnum (frame, "rpt_s", -1), &rpt_s);
+ frame_read_unsigned_register (frame, frame_map_name_to_regnum (frame, "rpt_e", -1), &rpt_e);
+ frame_read_unsigned_register (frame, frame_map_name_to_regnum (frame, "rpt_c", -1), &rpt_c);
fprintf_filtered (file, "PC=%04lx (0x%lx) PSW=%04lx RPT_S=%04lx RPT_E=%04lx RPT_C=%04lx\n",
(long) pc, (long) d10v_make_iaddr (pc), (long) psw,
(long) rpt_s, (long) rpt_e, (long) rpt_c);
Index: eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.30
diff -u -r1.30 eval.c
--- eval.c 30 Apr 2003 01:27:53 -0000 1.30
+++ eval.c 29 Jun 2003 15:01:32 -0000
@@ -454,7 +454,7 @@
(*pos) += 2;
if (val == NULL)
error ("Value of register %s not available.",
- frame_map_regnum_to_name (regno));
+ frame_map_regnum_to_name (get_selected_frame (), regno));
else
return val;
}
Index: expprint.c
===================================================================
RCS file: /cvs/src/src/gdb/expprint.c,v
retrieving revision 1.16
diff -u -r1.16 expprint.c
--- expprint.c 25 Feb 2003 21:36:17 -0000 1.16
+++ expprint.c 29 Jun 2003 15:01:32 -0000
@@ -27,7 +27,7 @@
#include "value.h"
#include "language.h"
#include "parser-defs.h"
-#include "frame.h" /* For frame_map_regnum_to_name. */
+#include "user-regs.h" /* For user_reg_map_regnum_to_name. */
#include "target.h"
#include "gdb_string.h"
#include "block.h"
@@ -126,8 +126,10 @@
case OP_REGISTER:
{
int regnum = longest_to_int (exp->elts[pc + 1].longconst);
+ const char *name = user_reg_map_regnum_to_name (current_gdbarch,
+ regnum);
(*pos) += 2;
- fprintf_filtered (stream, "$%s", frame_map_regnum_to_name (regnum));
+ fprintf_filtered (stream, "$%s", name);
return;
}
Index: findvar.c
===================================================================
RCS file: /cvs/src/src/gdb/findvar.c,v
retrieving revision 1.60
diff -u -r1.60 findvar.c
--- findvar.c 14 Jun 2003 22:35:23 -0000 1.60
+++ findvar.c 29 Jun 2003 15:01:33 -0000
@@ -34,7 +34,7 @@
#include "floatformat.h"
#include "symfile.h" /* for overlay functions */
#include "regcache.h"
-#include "builtin-regs.h"
+#include "user-regs.h"
#include "block.h"
/* Basic byte-swapping routines. GDB has needed these for a long time...
@@ -263,10 +263,10 @@
char raw_buffer[MAX_REGISTER_SIZE];
enum lval_type lval;
- /* Builtin registers lie completly outside of the range of normal
+ /* User registers lie completly outside of the range of normal
registers. Catch them early so that the target never sees them. */
if (regnum >= NUM_REGS + NUM_PSEUDO_REGS)
- return value_of_builtin_reg (regnum, frame);
+ return value_of_user_reg (regnum, frame);
frame_register (frame, regnum, &optim, &lval, &addr, &realnum, raw_buffer);
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.128
diff -u -r1.128 frame.c
--- frame.c 29 Jun 2003 13:27:26 -0000 1.128
+++ frame.c 29 Jun 2003 15:01:34 -0000
@@ -28,7 +28,7 @@
#include "regcache.h"
#include "gdb_assert.h"
#include "gdb_string.h"
-#include "builtin-regs.h"
+#include "user-regs.h"
#include "gdb_obstack.h"
#include "dummy-frame.h"
#include "sentinel-frame.h"
@@ -497,7 +497,7 @@
{
fprintf_unfiltered (gdb_stdlog,
"{ frame_register_unwind (frame=%d,regnum=\"%s\",...) ",
- frame->level, frame_map_regnum_to_name (regnum));
+ frame->level, frame_map_regnum_to_name (frame, regnum));
}
/* Require all but BUFFERP to be valid. A NULL BUFFERP indicates
@@ -773,42 +773,15 @@
includes builtin registers. */
int
-frame_map_name_to_regnum (const char *name, int len)
+frame_map_name_to_regnum (struct frame_info *frame, const char *name, int len)
{
- int i;
-
- if (len < 0)
- len = strlen (name);
-
- /* Search register name space. */
- for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
- if (REGISTER_NAME (i) && len == strlen (REGISTER_NAME (i))
- && strncmp (name, REGISTER_NAME (i), len) == 0)
- {
- return i;
- }
-
- /* Try builtin registers. */
- i = builtin_reg_map_name_to_regnum (name, len);
- if (i >= 0)
- {
- /* A builtin register doesn't fall into the architecture's
- register range. */
- gdb_assert (i >= NUM_REGS + NUM_PSEUDO_REGS);
- return i;
- }
-
- return -1;
+ return user_reg_map_name_to_regnum (get_frame_arch (frame), name, len);
}
const char *
-frame_map_regnum_to_name (int regnum)
+frame_map_regnum_to_name (struct frame_info *frame, int regnum)
{
- if (regnum < 0)
- return NULL;
- if (regnum < NUM_REGS + NUM_PSEUDO_REGS)
- return REGISTER_NAME (regnum);
- return builtin_reg_map_regnum_to_name (regnum);
+ return user_reg_map_regnum_to_name (get_frame_arch (frame), regnum);
}
/* Create a sentinel frame. */
Index: frame.h
===================================================================
RCS file: /cvs/src/src/gdb/frame.h,v
retrieving revision 1.103
diff -u -r1.103 frame.h
--- frame.h 21 Jun 2003 16:51:47 -0000 1.103
+++ frame.h 29 Jun 2003 15:01:34 -0000
@@ -409,8 +409,10 @@
includes builtin registers. If NAMELEN is negative, use the NAME's
length when doing the comparison. */
-extern int frame_map_name_to_regnum (const char *name, int namelen);
-extern const char *frame_map_regnum_to_name (int regnum);
+extern int frame_map_name_to_regnum (struct frame_info *frame,
+ const char *name, int namelen);
+extern const char *frame_map_regnum_to_name (struct frame_info *frame,
+ int regnum);
/* Unwind the PC. Strictly speaking return the resume address of the
calling frame. For GDB, `pc' is the resume address and not a
Index: infcmd.c
===================================================================
RCS file: /cvs/src/src/gdb/infcmd.c,v
retrieving revision 1.82
diff -u -r1.82 infcmd.c
--- infcmd.c 17 Jun 2003 20:28:13 -0000 1.82
+++ infcmd.c 29 Jun 2003 15:01:35 -0000
@@ -1651,7 +1651,8 @@
/* A register name? */
{
- int regnum = frame_map_name_to_regnum (start, end - start);
+ int regnum = frame_map_name_to_regnum (deprecated_selected_frame,
+ start, end - start);
if (regnum >= 0)
{
gdbarch_print_registers_info (current_gdbarch, gdb_stdout,
Index: parse.c
===================================================================
RCS file: /cvs/src/src/gdb/parse.c,v
retrieving revision 1.34
diff -u -r1.34 parse.c
--- parse.c 14 May 2003 17:43:18 -0000 1.34
+++ parse.c 29 Jun 2003 15:01:35 -0000
@@ -455,7 +455,8 @@
/* Handle tokens that refer to machine registers:
$ followed by a register name. */
- i = frame_map_name_to_regnum (str.ptr + 1, str.length - 1);
+ i = frame_map_name_to_regnum (deprecated_selected_frame,
+ str.ptr + 1, str.length - 1);
if (i >= 0)
goto handle_register;
Index: std-regs.c
===================================================================
RCS file: /cvs/src/src/gdb/std-regs.c,v
retrieving revision 1.7
diff -u -r1.7 std-regs.c
--- std-regs.c 8 Jun 2003 18:27:14 -0000 1.7
+++ std-regs.c 29 Jun 2003 15:01:36 -0000
@@ -22,7 +22,7 @@
Boston, MA 02111-1307, USA. */
#include "defs.h"
-#include "builtin-regs.h"
+#include "user-regs.h"
#include "frame.h"
#include "gdbtypes.h"
#include "value.h"
@@ -147,14 +147,14 @@
/* Frame based $fp, $pc, $sp and $ps. These only come into play
when the target does not define its own version of these
registers. */
- add_builtin_reg ("fp", value_of_builtin_frame_fp_reg);
- add_builtin_reg ("pc", value_of_builtin_frame_pc_reg);
- add_builtin_reg ("sp", value_of_builtin_frame_sp_reg);
- add_builtin_reg ("ps", value_of_builtin_frame_ps_reg);
+ user_reg_add_builtin ("fp", value_of_builtin_frame_fp_reg);
+ user_reg_add_builtin ("pc", value_of_builtin_frame_pc_reg);
+ user_reg_add_builtin ("sp", value_of_builtin_frame_sp_reg);
+ user_reg_add_builtin ("ps", value_of_builtin_frame_ps_reg);
/* NOTE: cagney/2002-04-05: For moment leave the $frame / $gdbframe
/ $gdb.frame disabled. It isn't yet clear which of the many
options is the best. */
if (0)
- add_builtin_reg ("frame", value_of_builtin_frame_reg);
+ user_reg_add_builtin ("frame", value_of_builtin_frame_reg);
}
Index: user-regs.c
===================================================================
RCS file: user-regs.c
diff -N user-regs.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ user-regs.c 29 Jun 2003 15:01:36 -0000
@@ -0,0 +1,186 @@
+/* User visible, per-frame registers, for GDB, the GNU debugger.
+
+ Copyright 2002 Free Software Foundation, Inc.
+
+ Contributed by Red Hat.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "user-regs.h"
+#include "gdbtypes.h"
+#include "gdb_string.h"
+#include "gdb_assert.h"
+#include "frame.h"
+
+/* A table of user registers.
+
+ User registers have regnum's that live above of the range [0
+ .. NUM_REGS + NUM_PSEUDO_REGS) (which is controlled by the target).
+ The target should never see a user register's regnum value.
+
+ Always append, never delete. By doing this, the relative regnum
+ (offset from NUM_REGS + NUM_PSEUDO_REGS) assigned to each user
+ register never changes. */
+
+struct user_reg
+{
+ const char *name;
+ struct value *(*read) (struct frame_info * frame);
+};
+
+struct user_regs
+{
+ struct user_reg *user;
+ int nr;
+};
+
+static void
+append_user_reg (struct user_regs *regs,
+ const char *name, user_reg_read_ftype *read)
+{
+ regs->nr++;
+ regs->user = xrealloc (regs->user,
+ regs->nr * sizeof (struct user_reg));
+ regs->user[regs->nr - 1].name = name;
+ regs->user[regs->nr - 1].read = read;
+}
+
+/* An array of the builtin user registers. */
+
+static struct user_regs builtin_user_regs;
+
+void
+user_reg_add_builtin (const char *name, user_reg_read_ftype *read)
+{
+ append_user_reg (&builtin_user_regs, name, read);
+}
+
+/* Per-architecture user registers. Start with the builtin user
+ registers and then, again, append. */
+
+static struct gdbarch_data *user_regs_data;
+
+static void *
+user_regs_init (struct gdbarch *gdbarch)
+{
+ int i;
+ struct user_regs *regs = XMALLOC (struct user_regs);
+ memset (regs, 0, sizeof (struct user_regs));
+ for (i = 0; i < builtin_user_regs.nr; i++)
+ append_user_reg (regs, builtin_user_regs.user[i].name,
+ builtin_user_regs.user[i].read);
+ return regs;
+}
+
+static void
+user_regs_free (struct gdbarch *gdbarch, void *data)
+{
+ struct user_regs *regs = data;
+ xfree (regs->user);
+ xfree (regs);
+}
+
+void
+user_reg_add (struct gdbarch *gdbarch, const char *name,
+ user_reg_read_ftype *read)
+{
+ struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
+ if (regs == NULL)
+ {
+ /* ULGH, called during architecture initialization. Patch
+ things up. */
+ regs = user_regs_init (gdbarch);
+ set_gdbarch_data (gdbarch, user_regs_data, regs);
+ }
+ append_user_reg (regs, name, read);
+}
+
+int
+user_reg_map_name_to_regnum (struct gdbarch *gdbarch, const char *name,
+ int len)
+{
+ /* Make life easy, set the len to something reasonable. */
+ if (len < 0)
+ len = strlen (name);
+
+ /* Search register name space first - always let an architecture
+ specific register override the user registers. */
+ {
+ int i;
+ int maxregs = (gdbarch_num_regs (gdbarch)
+ + gdbarch_num_pseudo_regs (gdbarch));
+ for (i = 0; i < maxregs; i++)
+ {
+ const char *regname = gdbarch_register_name (gdbarch, i);
+ if (regname != NULL && len == strlen (regname)
+ && strncmp (regname, name, len) == 0)
+ {
+ return i;
+ }
+ }
+ }
+
+ /* Search the user name space. */
+ {
+ struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
+ int reg;
+ for (reg = 0; reg < regs->nr; reg++)
+ {
+ if ((len < 0 && strcmp (regs->user[reg].name, name))
+ || (len == strlen (regs->user[reg].name)
+ && strncmp (regs->user[reg].name, name, len) == 0))
+ return NUM_REGS + NUM_PSEUDO_REGS + reg;
+ }
+ }
+
+ return -1;
+}
+
+const char *
+user_reg_map_regnum_to_name (struct gdbarch *gdbarch, int regnum)
+{
+ int maxregs = (gdbarch_num_regs (gdbarch)
+ + gdbarch_num_pseudo_regs (gdbarch));
+ struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
+ if (regnum < 0)
+ return NULL;
+ if (regnum < maxregs)
+ return gdbarch_register_name (gdbarch, regnum);
+ if (regnum < (maxregs + regs->nr))
+ return regs->user[regnum - maxregs].name;
+ return NULL;
+}
+
+struct value *
+value_of_user_reg (int regnum, struct frame_info *frame)
+{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
+ int reg = regnum - (NUM_REGS + NUM_PSEUDO_REGS);
+ gdb_assert (reg >= 0 && reg < regs->nr);
+ return regs->user[reg].read (frame);
+}
+
+extern initialize_file_ftype _initialize_user_regs; /* -Wmissing-prototypes */
+
+void
+_initialize_user_regs (void)
+{
+ user_regs_data = register_gdbarch_data (user_regs_init, user_regs_free);
+}
Index: user-regs.h
===================================================================
RCS file: user-regs.h
diff -N user-regs.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ user-regs.h 29 Jun 2003 15:01:36 -0000
@@ -0,0 +1,70 @@
+/* Per-frame user registers, for GDB, the GNU debugger.
+
+ Copyright 2002, 2003 Free Software Foundation, Inc.
+
+ Contributed by Red Hat.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef USER_REGS_H
+#define USER_REGS_H
+
+/* Implement both builtin, and architecture specific, per-frame user
+ visible registers.
+
+ Builtin registers apply to all architectures, where as architecture
+ specific registers are present when the architecture is selected.
+
+ These registers are assigned register numbers outside the
+ architecture's register range [0 .. NUM_REGS + NUM_PSEUDO_REGS).
+ Their values should be constructed using per-frame information. */
+
+/* TODO: cagney/2003-06-27: Need to think more about how these
+ registers are added, read, and modified. At present they are kind
+ of assumed to be read-only. Should it, for instance, return a
+ register descriptor that contains all the relvent access methods. */
+
+struct frame_info;
+
+/* Given an architecture, map a user visible register name onto its
+ index. */
+
+extern int user_reg_map_name_to_regnum (struct gdbarch *gdbarch,
+ const char *str, int len);
+
+extern const char *user_reg_map_regnum_to_name (struct gdbarch *gdbarch,
+ int regnum);
+
+/* Return the value of the frame register in the specified frame.
+
+ Note; These methods return a "struct value" instead of the raw
+ bytes as, at the time the register is being added, the type needed
+ to describe the register has not bee initialized. */
+
+typedef struct value *(user_reg_read_ftype) (struct frame_info *frame);
+extern struct value *value_of_user_reg (int regnum, struct frame_info *frame);
+
+/* Add a builtin register (present in all architectures). */
+extern void user_reg_add_builtin (const char *name,
+ user_reg_read_ftype *read);
+
+/* Add a per-architecture frame register. */
+extern void user_reg_add (struct gdbarch *gdbarch, const char *name,
+ user_reg_read_ftype *read);
+
+#endif