* [WIP/RFC] MIPS registers overhaul
@ 2003-05-10 0:25 Kevin Buettner
2003-05-10 20:30 ` Andrew Cagney
0 siblings, 1 reply; 46+ messages in thread
From: Kevin Buettner @ 2003-05-10 0:25 UTC (permalink / raw)
To: gdb-patches
The patch below represents the results of trying to fix two problems
related to floating point registers, stumbling at various points along
the way, and realizing that I needed to fix even more...
The two problems related to floating point registers that I started out
trying to fix are the following:
1) On mips64, it's not possible to set a floating point register to
a single precision value.
2) Again, on mips64, when running a program using the o32 ABI, floating
point doubles were not being fetched from GDB's regcache correctly.
For o32, floating point doubles are represented using register pairs,
but, for mips64, each register is stored in a 64-bit container. When
attempting to retrieve the value of a 64-bit double that should
be retrieved by taking 32-bits from a pair, the single 64-bit container
was being considered to be the value of the double.
Problem 1 was solved by introducing a union type for floating point
registers. When attempting to display a value using ``print'', you'll
see (with my patch) something like this:
(gdb) p $f20
$1 = {i = 4621199872640208077, f = -107374184, d = 8.9000000000000004}
(If someone can think of more meaningful, but still terse field names for
the above, please let me know.)
If you want to set the register, you can do it as follows:
(gdb) set $f20.d=2.3
(gdb) p $f20
$2 = {i = 4612361558371493478, f = 2.72008302e+23, d = 2.2999999999999998}
(gdb) set $f20.f=2.2
(gdb) p $f20
$3 = {i = 4612361557728087245, f = 2.20000005, d = 2.2999997142702342}
(gdb) set $f20.i=42
(gdb) p $f20
$4 = {i = 42, f = 5.88545355e-44, d = 2.0750757125332355e-322}
Also, you can still do:
(gdb) set $f20=3.3
(gdb) p $f20
$5 = {i = 4614613358185178726, f = 2.72008302e+23, d = 3.2999999999999998}
Problem 2 was solved by introducing pseudo-registers for the floating point
registers. Along the way (last Friday, I think), I ran into an assertion
failure which caused me to make even more extensive changes to the MIPS code.
BTW, the raw floating point registers are still accessible. Doing
"info registers raw" will display all of the raw registers. Or, if
you know the names of the registers you want to display, you can do,
e.g, "info registers raw_f20".
Which reminds me... I've introduced two sets of register numbers. I
called these the "cooked" and "raw" regnums. In many cases, the
cooked and raw numbers are the same. (They'll usually be the same
when the raw and cooked types are the same.) In the cases where the
numbers are different, the cooked number is a pseudo register number
and the corresponding raw register is (usually) used to determine the
value of cooked value. Raw registers numbers should be used by the
lower layers of GDB which communicate with the target and need to
populate GDB's regcache. The cooked registers *should* be used almost
everywhere else. Except they aren't at the moment. In particular,
most of mips-tdep.c wants to still operate on "raw" register data.
(Anywhere you see a byte order check, that's a clue that raw register
numbers should still be used.) So, in order to prevent this patch from
becoming even larger than it already is, much of mips-tdep.c still
uses raw register numbers. These should (probably) be cleaned up some
day to use cooked numbers instead. (I need to check to make sure I
have this as a comment in the code somewhere...)
For the o32 case that I was originally trying to fix, we end up
creating 16 64-bit cooked floating point registers of the union type
mentioned above. The raw floating point registers (in pairs) are used
to construct the cooked value. It's also possible to end up with no
cooked floating point registers or 32-floating floating point
registers, either 32- or 64-bit. (The values of FP_REGISTER_DOUBLE
and MIPS_FPU_TYPE influence what exactly gets done.)
Anyway, here it is. Any suggestions on how to break this patch up so
that it can be sensibly reviewed will be very much appreciated. (It
seems that much of what I've done is interdependent...)
* mdebugread.c, mips-linux-nat.c, mips-linux-tdep.c, mips-nat.c,
mips-tdep.c, mipsnbsd-nat.c, remote-mips.c, config/mips/nm-riscos.h
(ZERO_REGNUM, V0_REGNUM, A0_REGNUM, T9_REGNUM, SP_REGNUM, RA_REGNUM)
(PS_REGNUM, HI_REGNUM, LO_REGNUM, BADVADDR_REGNUM, CAUSE_REGNUM)
(PC_REGNUM, FP0_REGNUM, FPA0_REGNUM, FCRCS_REGNUM, FIRST_EMBED_REGNUM)
(PRID_REGNUM, LAST_EMBED_REGNUM, MIPS_LAST_ARG_REGNUM)
(MIPS_LAST_FP_ARG_REGNUM: Replace references to these macros
with references to members in the mips_regnums struct.
* Makefile.in (mdebugread.o, mips-linux-nat.o, mips-nat.o): Add
dependency on $(mips_tdep_h).
(mips-tdep.o): Add dependency on $(reggroups_h).
* mdebugread.c (mips-tdep.h): Include.
(RA_REGNUM): Revise definition.
* mips-linux-nat.c (mips-tdep.h): Include.
* mips-nat.c (mips-tdep.h): Include.
(REGISTER_PTRACE_ADDR): Rewrite macro into function.
* mips-tdep.c (reggroups.h): Include.
(struct gdbarch_tdep): Move ``mips_last_arg_regnum'' and
``mips_last_fp_arg_regnum'' members (renamed slightly) to
the mips_regnums struct. Add new members ``raw_regnums''
and ``cooked_regnums''.
(MIPS_LAST_FP_ARG_REGNUM, MIPS_LAST_ARG_REGNUM): Delete
macros.
(FP_REGISTER_DOUBLE): Move location of macro definition earlier
in the file.
(mips_raw_regnums, mips_cooked_regnums): New accessor functions.
(mips2_fp_compat): Use FP_REGISTER_DOUBLE to help determine
return value.
(mips_type_float_double_register_big)
(mips_type_float_double_register_little)
(mips_type_float_single_register_big)
(mips_type_float_single_register_little): New static variables
representing types for MIPS (cooked) floating point registers.
(mips_generic_embed_reg_names): New static variable.
(mips_processor_reg_names): Rename to mips_embed_reg_names.
(reg_name): New function.
(mips_register_name): Rewritten to use reg_name().
(mips_tx39_embed_reg_names): New static array listing names
of tx39 embedded registers.
(mips_r3041_reg_names): Rename to mips_r3041_embed_reg_names.
Prune names to just those of the embedded registers.
(mips_r3051_reg_names): Rename to mips_r3051_embed_reg_names.
Prune names to just those of the embedded registers.
(mips_r3081_reg_names): Rename to mips_r3081_embed_reg_names.
Prune names to just those of the embedded registers.
(mips_lsi33k_reg_names): Disable this broken code.
(mips_processor_type_table): Change all ``regnames'' references
to those listed above. Add entry for "tx39".
(mips_register_raw_size, mips_register_convertible)
(mips_register_convert_to_virtual, mips_register_convert_to_raw)
(mips_register_convert_to_type, mips_register_convert_from_type):
Delete.
(mips_register_virtual_type): Rewrite so that registers in
range [0, NUM_REGS) have a type whose size is the same as
that expected by the remote protocol. Pseudo-registers
above this range are give more user-friendly types.
(mips_find_saved_regs): For the floating point registers, put
references to both the cooked and raw regnums in the ``saved_regs''
array.
(mips_raw_reggroup): New static global.
(mips_init_reggroups, mips_add_reggroups, mips_register_reggroup_p)
(mips_is_floating_point_register, mips_is_raw_register)
(mips_is_general_purpose_register)
(build_mips_type_float_double_register_big)
(build_mips_type_float_double_register_little)
(build_mips_type_float_single_register_big)
(build_mips_type_float_single_register_little)
(cooked_regnum_to_raw_regnum, mips_pseudo_register_read)
(mips_psuedo_register_write): New functions.
(mips_read_fp_register_double): Simplify.
(mips_print_fp_register): Revise, taking into account the
fact that floating point registers are now pseudo registers.
(mips_print_register): Eliminate references to
REGISTER_VIRTUAL_TYPE().
(do_fp_register_row): Return early for no-name registers.
(do_gp_register_row): Eliminate references to REGISTER_VIRTUAL_TYPE().
Change logic to not break out of row printing loop when a non-general
purpose register is seen.
(mips_do_registers_info): Account for the fact that we now have
pseudo registers. Print the general purpose registers and the
floating point registers in seperate passes.
(mips_set_processor_type): Refer to ``mips_embed_reg_names''
instead of ``mips_processor_reg_names''.
(mips_stab_reg_to_regnum, mips_dwarf_dwarf2_ecoff_reg_to_regnum):
Add case for dealing with 16 cooked floating point registers.
(mips_gdbarch_init): Don't call set_gdbarch_register_raw_size(),
set_gdbarch_register_convertible(),
set_gdbarch_register_convert_to_virtual(), or
set_gdbarch_register_convert_to_raw() any longer. Initialize
tdep->raw_regnums and tdep->cooked_regnums. Initialize register
groups. Invoke set_gdbarch_sp_regnum() and set_gdbarch_pc_regnum().
(mips_dump_regnums): New function.
(mips_dump_tdep): Call mips_dump_regnums() to dump new members
of struct gdbarch_tdep. Don't dump things which've been deleted.
(_initialize_mips_tdep): Invoke mips_init_reggroups ().
Initialize mips_type_float_double_register_big,
mips_type_float_double_register_little,
mips_type_float_single_register_big, and
mips_type_float_single_register_little.
* mips-tdep.h (mips_regnums): New struct.
(mips_raw_regnums, mips_cooked_regnums): New functions.
* mipsnbsd-nat.c (mips-tdep.h): Include.
* remote-mips.c (mips-tdep.h): Include.
* config/mips/tm-irix3.h (MIPS_REGISTER_NAMES, FP0_REGNUM)
(PC_REGNUM, CAUSE_REGNUM, BADVADDR_REGNUM, HI_REGNUM, LO_REGNUM)
(FCRCS_REGNUM, FCRIR_REGNUM): Delete.
* config/mips/tm-irix5.h (REGISTER_BYTES, REGISTER_BYTE)
(REGISTER_VIRTUAL_TYPE): Delete.
* config/mips/tm-irix6.h (MIPS_REGISTER_NAMES, FP0_REGNUM)
(PC_REGNUM, CAUSE_REGNUM, BADVADDR_REGNUM, HI_REGNUM, LO_REGNUM)
(FCRCS_REGNUM, FCRIR_REGNUM, REGISTER_BYTE): Delete.
(REGISTER_VIRTUAL_TYPE): Delete #undef.
* config/mips/tmp-mips.h (MIPS_REGISTER_NAMES, ZERO_REGNUM)
(V0_REGNUM, A0_REGNUM, T9_REGNUM, SP_REGNUM, RA_REGNUM, PS_REGNUM)
(HI_REGNUM, LO_REGNUM, BADVADDR_REGNUM, CAUSE_REGNUM, PC_REGNUM)
(FP0_REGNUM, FPA0_REGNUM, FCRCS_REGNUM, FCRIR_REGNUM)
(UNUSED_REGNUM, FIRST_EMBED_REGNUM, PRID_REGNUM, LAST_EMBED_REGNUM)
(REGISTER_BYTE, REGISTER_VIRTUAL_TYPE)
(mips_register_convert_to_type, mips_register_convert_from_type)
(MIPS_REGISTER_CONVERT_TO_TYPE, MIPS_REGISTER_CONVERT_FROM_TYPE):
Delete.
* config/mips/tm-mips64.h (REGISTER_VIRTUAL_TYPE): Delete.
* config/mips/tm-tx39.h, config/mips/tm-tx39l.h
(MIPS_REGISTER_NAMES): Delete.
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.374
diff -u -p -r1.374 Makefile.in
--- Makefile.in 5 May 2003 18:33:10 -0000 1.374
+++ Makefile.in 9 May 2003 23:36:30 -0000
@@ -1953,7 +1953,7 @@ mdebugread.o: mdebugread.c $(defs_h) $(s
$(block_h) \
$(coff_sym_h) $(coff_symconst_h) $(gdb_stat_h) $(gdb_string_h) \
$(bfd_h) $(coff_ecoff_h) $(libaout_h) $(aout_aout64_h) \
- $(aout_stab_gnu_h) $(expression_h) $(language_h)
+ $(aout_stab_gnu_h) $(expression_h) $(language_h) $(mips_tdep_h)
mem-break.o: mem-break.c $(defs_h) $(symtab_h) $(breakpoint_h) $(inferior_h) \
$(target_h)
memattr.o: memattr.c $(defs_h) $(command_h) $(gdbcmd_h) $(memattr_h) \
@@ -1961,17 +1961,18 @@ memattr.o: memattr.c $(defs_h) $(command
minsyms.o: minsyms.c $(defs_h) $(gdb_string_h) $(symtab_h) $(bfd_h) \
$(symfile_h) $(objfiles_h) $(demangle_h) $(value_h) $(cp_abi_h)
mips-irix-tdep.o: mips-irix-tdep.c $(defs_h) $(osabi_h) $(elf_bfd_h)
-mips-linux-nat.o: mips-linux-nat.c $(defs_h)
+mips-linux-nat.o: mips-linux-nat.c $(defs_h) $(mips_tdep_h)
mips-linux-tdep.o: mips-linux-tdep.c $(defs_h) $(gdbcore_h) $(target_h) \
$(solib_svr4_h) $(osabi_h) $(gdb_string_h) $(mips_tdep_h) \
$(gdb_assert_h)
-mips-nat.o: mips-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(regcache_h)
+mips-nat.o: mips-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(regcache_h) \
+ $(mips_tdep_h)
mips-tdep.o: mips-tdep.c $(defs_h) $(gdb_string_h) $(gdb_assert_h) \
$(frame_h) $(inferior_h) $(symtab_h) $(value_h) $(gdbcmd_h) \
$(language_h) $(gdbcore_h) $(symfile_h) $(objfiles_h) \
$(gdbtypes_h) $(target_h) $(arch_utils_h) $(regcache_h) \
$(osabi_h) $(mips_tdep_h) $(block_h) $(opcode_mips_h) \
- $(elf_mips_h) $(elf_bfd_h) $(symcat_h)
+ $(elf_mips_h) $(elf_bfd_h) $(symcat_h) $(reggroups_h)
mipsm3-nat.o: mipsm3-nat.c $(defs_h) $(inferior_h) $(regcache_h)
mipsnbsd-nat.o: mipsnbsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) \
$(mipsnbsd_tdep_h)
Index: mdebugread.c
===================================================================
RCS file: /cvs/src/src/gdb/mdebugread.c,v
retrieving revision 1.44
diff -u -p -r1.44 mdebugread.c
--- mdebugread.c 19 Mar 2003 19:45:49 -0000 1.44
+++ mdebugread.c 9 May 2003 23:36:32 -0000
@@ -55,6 +55,9 @@
#include "gdb_assert.h"
#include "block.h"
+#include "mips-tdep.h"
+#define RA_REGNUM (mips_cooked_regnums (current_gdbarch)->ra_regnum)
+
/* These are needed if the tm.h file does not contain the necessary
mips specific definitions. */
@@ -69,9 +72,6 @@ typedef struct mips_extra_func_info
PDR pdr;
}
*mips_extra_func_info_t;
-#ifndef RA_REGNUM
-#define RA_REGNUM 0
-#endif
#endif
#ifdef USG
Index: mips-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-linux-nat.c,v
retrieving revision 1.4
diff -u -p -r1.4 mips-linux-nat.c
--- mips-linux-nat.c 30 Oct 2002 04:10:06 -0000 1.4
+++ mips-linux-nat.c 9 May 2003 23:36:32 -0000
@@ -20,6 +20,7 @@
Boston, MA 02111-1307, USA. */
#include "defs.h"
+#include "mips-tdep.h"
/* Pseudo registers can not be read. ptrace does not provide a way to
read (or set) PS_REGNUM, and there's no point in reading or setting
@@ -29,11 +30,13 @@
int
mips_linux_cannot_fetch_register (int regno)
{
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
if (REGISTER_NAME (regno)[0] == 0)
return 1;
- if (regno == PS_REGNUM)
+ if (regno == regnums->ps_regnum)
return 1;
- else if (regno == ZERO_REGNUM)
+ else if (regno == regnums->zero_regnum)
return 1;
else
return 0;
@@ -42,17 +45,19 @@ mips_linux_cannot_fetch_register (int re
int
mips_linux_cannot_store_register (int regno)
{
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
if (REGISTER_NAME (regno)[0] == 0)
return 1;
- if (regno == PS_REGNUM)
+ if (regno == regnums->ps_regnum)
return 1;
- else if (regno == ZERO_REGNUM)
+ else if (regno == regnums->zero_regnum)
return 1;
- else if (regno == BADVADDR_REGNUM)
+ else if (regno == regnums->badvaddr_regnum)
return 1;
- else if (regno == CAUSE_REGNUM)
+ else if (regno == regnums->cause_regnum)
return 1;
- else if (regno == FCRIR_REGNUM)
+ else if (regno == regnums->fcrir_regnum)
return 1;
else
return 0;
Index: mips-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-linux-tdep.c,v
retrieving revision 1.9
diff -u -p -r1.9 mips-linux-tdep.c
--- mips-linux-tdep.c 24 Dec 2002 19:21:10 -0000 1.9
+++ mips-linux-tdep.c 9 May 2003 23:36:32 -0000
@@ -72,8 +72,9 @@ mips_linux_get_longjmp_target (CORE_ADDR
{
CORE_ADDR jb_addr;
char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
+ const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
- jb_addr = read_register (A0_REGNUM);
+ jb_addr = read_register (regnums->a0_regnum);
if (target_read_memory (jb_addr
+ MIPS_LINUX_JB_PC * MIPS_LINUX_JB_ELEMENT_SIZE,
@@ -105,23 +106,25 @@ supply_gregset (elf_gregset_t *gregsetp)
int regi;
elf_greg_t *regp = *gregsetp;
char *zerobuf = alloca (MAX_REGISTER_RAW_SIZE);
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
memset (zerobuf, 0, MAX_REGISTER_RAW_SIZE);
for (regi = EF_REG0; regi <= EF_REG31; regi++)
supply_32bit_reg ((regi - EF_REG0), (char *)(regp + regi));
- supply_32bit_reg (LO_REGNUM, (char *)(regp + EF_LO));
- supply_32bit_reg (HI_REGNUM, (char *)(regp + EF_HI));
+ supply_32bit_reg (regnums->lo_regnum, (char *)(regp + EF_LO));
+ supply_32bit_reg (regnums->hi_regnum, (char *)(regp + EF_HI));
- supply_32bit_reg (PC_REGNUM, (char *)(regp + EF_CP0_EPC));
- supply_32bit_reg (BADVADDR_REGNUM, (char *)(regp + EF_CP0_BADVADDR));
- supply_32bit_reg (PS_REGNUM, (char *)(regp + EF_CP0_STATUS));
- supply_32bit_reg (CAUSE_REGNUM, (char *)(regp + EF_CP0_CAUSE));
+ supply_32bit_reg (regnums->pc_regnum, (char *)(regp + EF_CP0_EPC));
+ supply_32bit_reg (regnums->badvaddr_regnum, (char *)(regp + EF_CP0_BADVADDR));
+ supply_32bit_reg (regnums->ps_regnum, (char *)(regp + EF_CP0_STATUS));
+ supply_32bit_reg (regnums->cause_regnum, (char *)(regp + EF_CP0_CAUSE));
/* Fill inaccessible registers with zero. */
- supply_register (UNUSED_REGNUM, zerobuf);
- for (regi = FIRST_EMBED_REGNUM; regi < LAST_EMBED_REGNUM; regi++)
+ for (regi = regnums->first_embed_regnum;
+ regi < regnums->last_embed_regnum;
+ regi++)
supply_register (regi, zerobuf);
}
@@ -133,18 +136,19 @@ fill_gregset (elf_gregset_t *gregsetp, i
int regaddr, regi;
elf_greg_t *regp = *gregsetp;
void *dst;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
if (regno == -1)
{
memset (regp, 0, sizeof (elf_gregset_t));
for (regi = 0; regi < 32; regi++)
fill_gregset (gregsetp, regi);
- fill_gregset (gregsetp, LO_REGNUM);
- fill_gregset (gregsetp, HI_REGNUM);
- fill_gregset (gregsetp, PC_REGNUM);
- fill_gregset (gregsetp, BADVADDR_REGNUM);
- fill_gregset (gregsetp, PS_REGNUM);
- fill_gregset (gregsetp, CAUSE_REGNUM);
+ fill_gregset (gregsetp, regnums->lo_regnum);
+ fill_gregset (gregsetp, regnums->hi_regnum);
+ fill_gregset (gregsetp, regnums->pc_regnum);
+ fill_gregset (gregsetp, regnums->badvaddr_regnum);
+ fill_gregset (gregsetp, regnums->ps_regnum);
+ fill_gregset (gregsetp, regnums->cause_regnum);
return;
}
@@ -157,27 +161,18 @@ fill_gregset (elf_gregset_t *gregsetp, i
}
regaddr = -1;
- switch (regno)
- {
- case LO_REGNUM:
- regaddr = EF_LO;
- break;
- case HI_REGNUM:
- regaddr = EF_HI;
- break;
- case PC_REGNUM:
- regaddr = EF_CP0_EPC;
- break;
- case BADVADDR_REGNUM:
- regaddr = EF_CP0_BADVADDR;
- break;
- case PS_REGNUM:
- regaddr = EF_CP0_STATUS;
- break;
- case CAUSE_REGNUM:
- regaddr = EF_CP0_CAUSE;
- break;
- }
+ if (regno == regnums->lo_regnum)
+ regaddr = EF_LO;
+ else if (regno == regnums->hi_regnum)
+ regaddr = EF_HI;
+ else if (regno == regnums->pc_regnum)
+ regaddr = EF_CP0_EPC;
+ else if (regno == regnums->badvaddr_regnum)
+ regaddr = EF_CP0_BADVADDR;
+ else if (regno == regnums->ps_regnum)
+ regaddr = EF_CP0_STATUS;
+ else if (regno == regnums->cause_regnum)
+ regaddr = EF_CP0_CAUSE;
if (regaddr != -1)
{
@@ -193,17 +188,17 @@ supply_fpregset (elf_fpregset_t *fpregse
{
register int regi;
char *zerobuf = alloca (MAX_REGISTER_RAW_SIZE);
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
memset (zerobuf, 0, MAX_REGISTER_RAW_SIZE);
for (regi = 0; regi < 32; regi++)
- supply_register (FP0_REGNUM + regi,
- (char *)(*fpregsetp + regi));
+ supply_register (regnums->fp0_regnum + regi, (char *)(*fpregsetp + regi));
- supply_register (FCRCS_REGNUM, (char *)(*fpregsetp + 32));
+ supply_register (regnums->fcrcs_regnum, (char *)(*fpregsetp + 32));
- /* FIXME: how can we supply FCRIR_REGNUM? The ABI doesn't tell us. */
- supply_register (FCRIR_REGNUM, zerobuf);
+ /* FIXME: how can we supply FCRIR? The ABI doesn't tell us. */
+ supply_register (regnums->fcrir_regnum, zerobuf);
}
/* Likewise, pack one or all floating point registers into an
@@ -213,14 +208,15 @@ void
fill_fpregset (elf_fpregset_t *fpregsetp, int regno)
{
char *from, *to;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
- if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
+ if ((regno >= regnums->fp0_regnum) && (regno < regnums->fp0_regnum + 32))
{
from = (char *) &deprecated_registers[REGISTER_BYTE (regno)];
- to = (char *) (*fpregsetp + regno - FP0_REGNUM);
- memcpy (to, from, REGISTER_RAW_SIZE (regno - FP0_REGNUM));
+ to = (char *) (*fpregsetp + regno - regnums->fp0_regnum);
+ memcpy (to, from, REGISTER_RAW_SIZE (regno - regnums->fp0_regnum));
}
- else if (regno == FCRCS_REGNUM)
+ else if (regno == regnums->fcrcs_regnum)
{
from = (char *) &deprecated_registers[REGISTER_BYTE (regno)];
to = (char *) (*fpregsetp + 32);
@@ -231,8 +227,8 @@ fill_fpregset (elf_fpregset_t *fpregsetp
int regi;
for (regi = 0; regi < 32; regi++)
- fill_fpregset (fpregsetp, FP0_REGNUM + regi);
- fill_fpregset(fpregsetp, FCRCS_REGNUM);
+ fill_fpregset (fpregsetp, regnums->fp0_regnum + regi);
+ fill_fpregset(fpregsetp, regnums->fcrcs_regnum);
}
}
@@ -243,27 +239,28 @@ static CORE_ADDR
mips_linux_register_addr (int regno, CORE_ADDR blockend)
{
int regaddr;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
if (regno < 0 || regno >= NUM_REGS)
error ("Bogon register number %d.", regno);
if (regno < 32)
regaddr = regno;
- else if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
- regaddr = FPR_BASE + (regno - FP0_REGNUM);
- else if (regno == PC_REGNUM)
+ else if ((regno >= regnums->fp0_regnum) && (regno < regnums->fp0_regnum + 32))
+ regaddr = FPR_BASE + (regno - regnums->fp0_regnum);
+ else if (regno == regnums->pc_regnum)
regaddr = PC;
- else if (regno == CAUSE_REGNUM)
+ else if (regno == regnums->cause_regnum)
regaddr = CAUSE;
- else if (regno == BADVADDR_REGNUM)
+ else if (regno == regnums->badvaddr_regnum)
regaddr = BADVADDR;
- else if (regno == LO_REGNUM)
+ else if (regno == regnums->lo_regnum)
regaddr = MMLO;
- else if (regno == HI_REGNUM)
+ else if (regno == regnums->hi_regnum)
regaddr = MMHI;
- else if (regno == FCRCS_REGNUM)
+ else if (regno == regnums->fcrcs_regnum)
regaddr = FPC_CSR;
- else if (regno == FCRIR_REGNUM)
+ else if (regno == regnums->fcrir_regnum)
regaddr = FPC_EIR;
else
error ("Unknowable register number %d.", regno);
@@ -360,8 +357,9 @@ mips64_linux_get_longjmp_target (CORE_AD
CORE_ADDR jb_addr;
void *buf = alloca (TARGET_PTR_BIT / TARGET_CHAR_BIT);
int element_size = TARGET_PTR_BIT == 32 ? 4 : 8;
+ const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
- jb_addr = read_register (A0_REGNUM);
+ jb_addr = read_register (regnums->a0_regnum);
if (target_read_memory (jb_addr + MIPS64_LINUX_JB_PC * element_size,
buf, TARGET_PTR_BIT / TARGET_CHAR_BIT))
@@ -380,23 +378,25 @@ mips64_supply_gregset (mips64_elf_gregse
int regi;
mips64_elf_greg_t *regp = *gregsetp;
char *zerobuf = alloca (MAX_REGISTER_RAW_SIZE);
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
memset (zerobuf, 0, MAX_REGISTER_RAW_SIZE);
for (regi = MIPS64_EF_REG0; regi <= MIPS64_EF_REG31; regi++)
supply_register ((regi - MIPS64_EF_REG0), (char *)(regp + regi));
- supply_register (LO_REGNUM, (char *)(regp + MIPS64_EF_LO));
- supply_register (HI_REGNUM, (char *)(regp + MIPS64_EF_HI));
+ supply_register (regnums->lo_regnum, (char *)(regp + MIPS64_EF_LO));
+ supply_register (regnums->hi_regnum, (char *)(regp + MIPS64_EF_HI));
- supply_register (PC_REGNUM, (char *)(regp + MIPS64_EF_CP0_EPC));
- supply_register (BADVADDR_REGNUM, (char *)(regp + MIPS64_EF_CP0_BADVADDR));
- supply_register (PS_REGNUM, (char *)(regp + MIPS64_EF_CP0_STATUS));
- supply_register (CAUSE_REGNUM, (char *)(regp + MIPS64_EF_CP0_CAUSE));
+ supply_register (regnums->pc_regnum, (char *)(regp + MIPS64_EF_CP0_EPC));
+ supply_register (regnums->badvaddr_regnum, (char *)(regp + MIPS64_EF_CP0_BADVADDR));
+ supply_register (regnums->ps_regnum, (char *)(regp + MIPS64_EF_CP0_STATUS));
+ supply_register (regnums->cause_regnum, (char *)(regp + MIPS64_EF_CP0_CAUSE));
/* Fill inaccessible registers with zero. */
- supply_register (UNUSED_REGNUM, zerobuf);
- for (regi = FIRST_EMBED_REGNUM; regi < LAST_EMBED_REGNUM; regi++)
+ for (regi = regnums->first_embed_regnum;
+ regi < regnums->last_embed_regnum;
+ regi++)
supply_register (regi, zerobuf);
}
@@ -408,18 +408,19 @@ mips64_fill_gregset (mips64_elf_gregset_
int regaddr, regi;
mips64_elf_greg_t *regp = *gregsetp;
void *src, *dst;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
if (regno == -1)
{
memset (regp, 0, sizeof (mips64_elf_gregset_t));
for (regi = 0; regi < 32; regi++)
mips64_fill_gregset (gregsetp, regi);
- mips64_fill_gregset (gregsetp, LO_REGNUM);
- mips64_fill_gregset (gregsetp, HI_REGNUM);
- mips64_fill_gregset (gregsetp, PC_REGNUM);
- mips64_fill_gregset (gregsetp, BADVADDR_REGNUM);
- mips64_fill_gregset (gregsetp, PS_REGNUM);
- mips64_fill_gregset (gregsetp, CAUSE_REGNUM);
+ mips64_fill_gregset (gregsetp, regnums->lo_regnum);
+ mips64_fill_gregset (gregsetp, regnums->hi_regnum);
+ mips64_fill_gregset (gregsetp, regnums->pc_regnum);
+ mips64_fill_gregset (gregsetp, regnums->badvaddr_regnum);
+ mips64_fill_gregset (gregsetp, regnums->ps_regnum);
+ mips64_fill_gregset (gregsetp, regnums->cause_regnum);
return;
}
@@ -432,27 +433,18 @@ mips64_fill_gregset (mips64_elf_gregset_
}
regaddr = -1;
- switch (regno)
- {
- case LO_REGNUM:
+ if (regno == regnums->lo_regnum)
regaddr = MIPS64_EF_LO;
- break;
- case HI_REGNUM:
+ else if (regno == regnums->hi_regnum)
regaddr = MIPS64_EF_HI;
- break;
- case PC_REGNUM:
+ else if (regno == regnums->pc_regnum)
regaddr = MIPS64_EF_CP0_EPC;
- break;
- case BADVADDR_REGNUM:
+ else if (regno == regnums->badvaddr_regnum)
regaddr = MIPS64_EF_CP0_BADVADDR;
- break;
- case PS_REGNUM:
+ else if (regno == regnums->ps_regnum)
regaddr = MIPS64_EF_CP0_STATUS;
- break;
- case CAUSE_REGNUM:
+ else if (regno == regnums->cause_regnum)
regaddr = MIPS64_EF_CP0_CAUSE;
- break;
- }
if (regaddr != -1)
{
@@ -468,17 +460,17 @@ mips64_supply_fpregset (mips64_elf_fpreg
{
register int regi;
char *zerobuf = alloca (MAX_REGISTER_RAW_SIZE);
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
memset (zerobuf, 0, MAX_REGISTER_RAW_SIZE);
for (regi = 0; regi < 32; regi++)
- supply_register (FP0_REGNUM + regi,
- (char *)(*fpregsetp + regi));
+ supply_register (regnums->fp0_regnum + regi, (char *)(*fpregsetp + regi));
- supply_register (FCRCS_REGNUM, (char *)(*fpregsetp + 32));
+ supply_register (regnums->fcrcs_regnum, (char *)(*fpregsetp + 32));
- /* FIXME: how can we supply FCRIR_REGNUM? The ABI doesn't tell us. */
- supply_register (FCRIR_REGNUM, zerobuf);
+ /* FIXME: how can we supply FCRIR? The ABI doesn't tell us. */
+ supply_register (regnums->fcrir_regnum, zerobuf);
}
/* Likewise, pack one or all floating point registers into an
@@ -488,14 +480,15 @@ static void
mips64_fill_fpregset (mips64_elf_fpregset_t *fpregsetp, int regno)
{
char *from, *to;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
- if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
+ if ((regno >= regnums->fp0_regnum) && (regno < regnums->fp0_regnum + 32))
{
from = (char *) &deprecated_registers[REGISTER_BYTE (regno)];
- to = (char *) (*fpregsetp + regno - FP0_REGNUM);
- memcpy (to, from, REGISTER_RAW_SIZE (regno - FP0_REGNUM));
+ to = (char *) (*fpregsetp + regno - regnums->fp0_regnum);
+ memcpy (to, from, REGISTER_RAW_SIZE (regno - regnums->fp0_regnum));
}
- else if (regno == FCRCS_REGNUM)
+ else if (regno == regnums->fcrcs_regnum)
{
from = (char *) &deprecated_registers[REGISTER_BYTE (regno)];
to = (char *) (*fpregsetp + 32);
@@ -506,8 +499,8 @@ mips64_fill_fpregset (mips64_elf_fpregse
int regi;
for (regi = 0; regi < 32; regi++)
- mips64_fill_fpregset (fpregsetp, FP0_REGNUM + regi);
- mips64_fill_fpregset(fpregsetp, FCRCS_REGNUM);
+ mips64_fill_fpregset (fpregsetp, regnums->fp0_regnum + regi);
+ mips64_fill_fpregset(fpregsetp, regnums->fcrcs_regnum);
}
}
@@ -519,27 +512,28 @@ static CORE_ADDR
mips64_linux_register_addr (int regno, CORE_ADDR blockend)
{
int regaddr;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
if (regno < 0 || regno >= NUM_REGS)
error ("Bogon register number %d.", regno);
if (regno < 32)
regaddr = regno;
- else if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
- regaddr = MIPS64_FPR_BASE + (regno - FP0_REGNUM);
- else if (regno == PC_REGNUM)
+ else if ((regno >= regnums->fp0_regnum) && (regno < regnums->fp0_regnum + 32))
+ regaddr = MIPS64_FPR_BASE + (regno - regnums->fp0_regnum);
+ else if (regno == regnums->pc_regnum)
regaddr = MIPS64_PC;
- else if (regno == CAUSE_REGNUM)
+ else if (regno == regnums->cause_regnum)
regaddr = MIPS64_CAUSE;
- else if (regno == BADVADDR_REGNUM)
+ else if (regno == regnums->badvaddr_regnum)
regaddr = MIPS64_BADVADDR;
- else if (regno == LO_REGNUM)
+ else if (regno == regnums->lo_regnum)
regaddr = MIPS64_MMLO;
- else if (regno == HI_REGNUM)
+ else if (regno == regnums->hi_regnum)
regaddr = MIPS64_MMHI;
- else if (regno == FCRCS_REGNUM)
+ else if (regno == regnums->fcrcs_regnum)
regaddr = MIPS64_FPC_CSR;
- else if (regno == FCRIR_REGNUM)
+ else if (regno == regnums->fcrir_regnum)
regaddr = MIPS64_FPC_EIR;
else
error ("Unknowable register number %d.", regno);
Index: mips-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-nat.c,v
retrieving revision 1.10
diff -u -p -r1.10 mips-nat.c
--- mips-nat.c 29 Apr 2003 01:49:47 -0000 1.10
+++ mips-nat.c 9 May 2003 23:36:32 -0000
@@ -1,5 +1,5 @@
/* Low level DECstation interface to ptrace, for GDB when running native.
- Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1999, 2000, 2001
+ Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1999, 2000, 2001, 2003
Free Software Foundation, Inc.
Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
@@ -43,6 +43,7 @@
#undef JB_SR
#undef NJBREGS
#include <setjmp.h> /* For JB_XXX. */
+#include <mips-tdep.h>
/* Size of elements in jmpbuf */
@@ -51,16 +52,22 @@
/* Map gdb internal register number to ptrace ``address''.
These ``addresses'' are defined in DECstation <sys/ptrace.h> */
-#define REGISTER_PTRACE_ADDR(regno) \
- (regno < 32 ? GPR_BASE + regno \
- : regno == PC_REGNUM ? PC \
- : regno == CAUSE_REGNUM ? CAUSE \
- : regno == HI_REGNUM ? MMHI \
- : regno == LO_REGNUM ? MMLO \
- : regno == FCRCS_REGNUM ? FPC_CSR \
- : regno == FCRIR_REGNUM ? FPC_EIR \
- : regno >= FP0_REGNUM ? FPR_BASE + (regno - FP0_REGNUM) \
+static int
+register_ptrace_addr (int regno)
+{
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
+ return
+ (regno < 32 ? GPR_BASE + regno
+ : regno == regnums->pc_regnum ? PC
+ : regno == regnums->cause_regnum ? CAUSE
+ : regno == regnums->hi_regnum ? MMHI
+ : regno == regnums->lo_regnum ? MMLO
+ : regno == regnums->fcrcs_regnum ? FPC_CSR
+ : regno == regnums->fcrir_regnum ? FPC_EIR
+ : regno >= regnums->fp0_regnum ? FPR_BASE + (regno - regnums->fp0_regnum)
: 0)
+}
static void fetch_core_registers (char *, unsigned, int, CORE_ADDR);
@@ -73,13 +80,15 @@ fetch_inferior_registers (int regno)
char *buf = alloca (max_register_size (current_gdbarch));
register int i;
char *zerobuf = alloca (max_register_size (current_gdbarch));
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
memset (zerobuf, 0, max_register_size (current_gdbarch));
deprecated_registers_fetched ();
for (regno = 1; regno < NUM_REGS; regno++)
{
- regaddr = REGISTER_PTRACE_ADDR (regno);
+ regaddr = register_ptrace_addr (regno);
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
{
*(int *) &buf[i] = ptrace (PT_READ_U, PIDGET (inferior_ptid),
@@ -89,7 +98,7 @@ fetch_inferior_registers (int regno)
supply_register (regno, buf);
}
- supply_register (ZERO_REGNUM, zerobuf);
+ supply_register (regnums->zero_regnum, zerobuf);
/* Frame ptr reg must appear to be 0; it is faked by stack handling code. */
supply_register (DEPRECATED_FP_REGNUM, zerobuf);
}
@@ -103,15 +112,20 @@ store_inferior_registers (int regno)
{
register unsigned int regaddr;
char buf[80];
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
if (regno > 0)
{
- if (regno == ZERO_REGNUM || regno == PS_REGNUM
- || regno == BADVADDR_REGNUM || regno == CAUSE_REGNUM
- || regno == FCRIR_REGNUM || regno == DEPRECATED_FP_REGNUM
- || (regno >= FIRST_EMBED_REGNUM && regno <= LAST_EMBED_REGNUM))
+ if (regno == regnums->zero_regnum
+ || regno == regnums->ps_regnum
+ || regno == regnums->badvaddr_regnum
+ || regnums->regno == regnums->cause_regnum
+ || regno == regnums->fcrir_regnum
+ || regno == DEPRECATED_FP_REGNUM
+ || (regno >= regnums->first_embed_regnum
+ && regno <= regnums->last_embed_regnum))
return;
- regaddr = REGISTER_PTRACE_ADDR (regno);
+ regaddr = register_ptrace_addr (regno);
errno = 0;
ptrace (PT_WRITE_U, PIDGET (inferior_ptid), (PTRACE_ARG3_TYPE) regaddr,
read_register (regno));
@@ -139,9 +153,10 @@ get_longjmp_target (CORE_ADDR *pc)
{
CORE_ADDR jb_addr;
char *buf;
+ const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
buf = alloca (TARGET_PTR_BIT / TARGET_CHAR_BIT);
- jb_addr = read_register (A0_REGNUM);
+ jb_addr = read_register (regnums->a0_regnum);
if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
TARGET_PTR_BIT / TARGET_CHAR_BIT))
@@ -173,6 +188,7 @@ fetch_core_registers (char *core_reg_sec
register unsigned int addr;
int bad_reg = -1;
register reg_ptr = -reg_addr; /* Original u.u_ar0 is -reg_addr. */
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
char *zerobuf = alloca (max_register_size (current_gdbarch));
memset (zerobuf, 0, max_register_size (current_gdbarch));
@@ -208,7 +224,7 @@ fetch_core_registers (char *core_reg_sec
{
error ("Register %s not found in core file.", REGISTER_NAME (bad_reg));
}
- supply_register (ZERO_REGNUM, zerobuf);
+ supply_register (regnums->zero_regnum, zerobuf);
/* Frame ptr reg must appear to be 0; it is faked by stack handling code. */
supply_register (DEPRECATED_FP_REGNUM, zerobuf);
}
Index: mips-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-tdep.c,v
retrieving revision 1.195
diff -u -p -r1.195 mips-tdep.c
--- mips-tdep.c 5 May 2003 17:56:55 -0000 1.195
+++ mips-tdep.c 9 May 2003 23:36:34 -0000
@@ -42,6 +42,7 @@
#include "osabi.h"
#include "mips-tdep.h"
#include "block.h"
+#include "reggroups.h"
#include "opcode/mips.h"
#include "elf/mips.h"
@@ -124,24 +125,30 @@ struct gdbarch_tdep
enum mips_abi mips_abi;
enum mips_abi found_abi;
enum mips_fpu_type mips_fpu_type;
- int mips_last_arg_regnum;
- int mips_last_fp_arg_regnum;
int mips_default_saved_regsize;
int mips_fp_register_double;
int mips_default_stack_argsize;
int gdb_target_is_mips64;
int default_mask_address_p;
+
+ struct mips_regnums raw_regnums;
+ struct mips_regnums cooked_regnums;
+
+ char **regnames;
};
#define MIPS_EABI (gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI32 \
|| gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI64)
-#define MIPS_LAST_FP_ARG_REGNUM (gdbarch_tdep (current_gdbarch)->mips_last_fp_arg_regnum)
-
-#define MIPS_LAST_ARG_REGNUM (gdbarch_tdep (current_gdbarch)->mips_last_arg_regnum)
-
#define MIPS_FPU_TYPE (gdbarch_tdep (current_gdbarch)->mips_fpu_type)
+/* Indicate that the ABI makes use of double-precision registers
+ provided by the FPU (rather than combining pairs of registers to
+ form double-precision values). Do not use "TARGET_IS_MIPS64" to
+ determine if the ABI is using double-precision registers. See also
+ MIPS_FPU_TYPE. */
+#define FP_REGISTER_DOUBLE (gdbarch_tdep (current_gdbarch)->mips_fp_register_double)
+
/* Return the currently configured (or set) saved register size. */
#define MIPS_DEFAULT_SAVED_REGSIZE (gdbarch_tdep (current_gdbarch)->mips_default_saved_regsize)
@@ -157,6 +164,18 @@ mips_abi (struct gdbarch *gdbarch)
return gdbarch_tdep (gdbarch)->mips_abi;
}
+const struct mips_regnums *
+mips_raw_regnums (struct gdbarch *gdbarch)
+{
+ return &(gdbarch_tdep (gdbarch)->raw_regnums);
+}
+
+const struct mips_regnums *
+mips_cooked_regnums (struct gdbarch *gdbarch)
+{
+ return &(gdbarch_tdep (gdbarch)->cooked_regnums);
+}
+
static unsigned int
mips_saved_regsize (void)
{
@@ -266,9 +285,11 @@ mips_xfer_register (struct regcache *reg
static int
mips2_fp_compat (void)
{
+ const struct mips_regnums *cooked_regnums
+ = mips_cooked_regnums (current_gdbarch);
/* MIPS1 and MIPS2 have only 32 bit FPRs, and the FR bit is not
meaningful. */
- if (REGISTER_RAW_SIZE (FP0_REGNUM) == 4)
+ if (REGISTER_RAW_SIZE (cooked_regnums->fp0_regnum) == 4)
return 0;
#if 0
@@ -277,20 +298,13 @@ mips2_fp_compat (void)
/* Otherwise check the FR bit in the status register - it controls
the FP compatiblity mode. If it is clear we are in compatibility
mode. */
- if ((read_register (PS_REGNUM) & ST0_FR) == 0)
+ if ((read_register (cooked_regnums->ps_regnum) & ST0_FR) == 0)
return 1;
#endif
- return 0;
+ return !FP_REGISTER_DOUBLE;
}
-/* Indicate that the ABI makes use of double-precision registers
- provided by the FPU (rather than combining pairs of registers to
- form double-precision values). Do not use "TARGET_IS_MIPS64" to
- determine if the ABI is using double-precision registers. See also
- MIPS_FPU_TYPE. */
-#define FP_REGISTER_DOUBLE (gdbarch_tdep (current_gdbarch)->mips_fp_register_double)
-
/* The amount of space reserved on the stack for registers. This is
different to MIPS_SAVED_REGSIZE as it determines the alignment of
data allocated after the registers have run out. */
@@ -348,6 +362,14 @@ static void mips_read_fp_register_double
static struct type *mips_float_register_type (void);
static struct type *mips_double_register_type (void);
+/* Types used for cooked floating point registers. These are union
+ types which allow the user to view (or set) the floating point
+ register in a variety of ways. */
+static struct type *mips_type_float_double_register_big;
+static struct type *mips_type_float_double_register_little;
+static struct type *mips_type_float_single_register_big;
+static struct type *mips_type_float_single_register_little;
+
/* This value is the model of MIPS in use. It is derived from the value
of the PrID register. */
@@ -360,19 +382,20 @@ char *tmp_mips_processor_type;
static struct cmd_list_element *setmipscmdlist = NULL;
static struct cmd_list_element *showmipscmdlist = NULL;
-/* A set of original names, to be used when restoring back to generic
- registers from a specific set. */
-static char *mips_generic_reg_names[] = MIPS_REGISTER_NAMES;
-
-/* Integer registers 0 thru 31 are handled explicitly by
- mips_register_name(). Processor specific registers 32 and above
- are listed in the sets of register names assigned to
- mips_processor_reg_names. */
-static char **mips_processor_reg_names = mips_generic_reg_names;
+/* Names of generic embedded registers. */
+char *mips_generic_embed_reg_names[] = {
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+};
-/* Return the name of the register corresponding to REGNO. */
+/* Names of special purpose (embedded) registers. */
+static char **mips_embed_reg_names = mips_generic_embed_reg_names;
+
+/* Given a register number REGNO and set of register numbers assignments
+ REGNUMS, return the name for REGNO. If no name can be determined,
+ return NULL. */
static const char *
-mips_register_name (int regno)
+reg_name (int regno, const struct mips_regnums *regnums)
{
/* GPR names for all ABIs other than n32/n64. */
static char *mips_gpr_names[] = {
@@ -390,67 +413,135 @@ mips_register_name (int regno)
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
};
+ /* FPR names */
+ static char *mips_fpr_names[] = {
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+ };
+
enum mips_abi abi = mips_abi (current_gdbarch);
- /* The MIPS integer registers are always mapped from 0 to 31. The
- names of the registers (which reflects the conventions regarding
- register use) vary depending on the ABI. */
- if (0 <= regno && regno < 32)
+ /* ``zero_regnum'' is the first GPR. ``ra_regnum'' is the last GPR.
+ The names of the general purpose registers (which reflects the
+ conventions regarding register use) vary depending on the ABI. */
+ if (regnums->zero_regnum <= regno && regno <= regnums->ra_regnum)
{
if (abi == MIPS_ABI_N32 || abi == MIPS_ABI_N64)
- return mips_n32_n64_gpr_names[regno];
+ return mips_n32_n64_gpr_names[regno - regnums->zero_regnum];
else
- return mips_gpr_names[regno];
+ return mips_gpr_names[regno - regnums->zero_regnum];
}
- else if (32 <= regno && regno < NUM_REGS)
- return mips_processor_reg_names[regno - 32];
+ else if (regnums->fp0_regnum <= regno && regno <= regnums->fplast_regnum)
+ {
+ if (regnums->fplast_regnum - regnums->fp0_regnum + 1 == 16)
+ return mips_fpr_names[2 * (regno - regnums->fp0_regnum)];
+ else
+ return mips_fpr_names[regno - regnums->fp0_regnum];
+ }
+ else if (regno == regnums->ps_regnum)
+ return "sr";
+ else if (regno == regnums->lo_regnum)
+ return "lo";
+ else if (regno == regnums->hi_regnum)
+ return "hi";
+ else if (regno == regnums->badvaddr_regnum)
+ return "bad";
+ else if (regno == regnums->cause_regnum)
+ return "cause";
+ else if (regno == regnums->pc_regnum)
+ return "pc";
+ else if (regno == regnums->fcrcs_regnum)
+ return "fsr";
+ else if (regno == regnums->fcrir_regnum)
+ return "fir";
+ else if (regnums->first_embed_regnum <= regno
+ && regno <= regnums->last_embed_regnum)
+ return mips_embed_reg_names[regno - regnums->first_embed_regnum];
else
- internal_error (__FILE__, __LINE__,
- "mips_register_name: bad register number %d", regno);
+ return NULL;
+}
+
+/* Return the name of the register corresponding to REGNO. */
+static const char *
+mips_register_name (int regno)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ const char *name;
+
+ if (tdep->regnames == NULL)
+ tdep->regnames = xcalloc (NUM_REGS + NUM_PSEUDO_REGS, sizeof (char *));
+
+ gdb_assert (0 <= regno && regno < NUM_REGS + NUM_PSEUDO_REGS);
+
+ if (tdep->regnames[regno])
+ return tdep->regnames[regno];
+
+ name = reg_name (regno, mips_cooked_regnums (current_gdbarch));
+
+ if (name != NULL)
+ {
+ tdep->regnames[regno] = xstrdup (name);
+ return name;
+ }
+
+ name = reg_name (regno, mips_raw_regnums (current_gdbarch));
+
+ if (name != NULL && *name != '\0')
+ {
+ char *raw_name = xmalloc (strlen (name) + 4 /* for "raw_" */ + 1);
+ strcpy (raw_name, "raw_");
+ strcat (raw_name, name);
+ tdep->regnames[regno] = raw_name;
+ return raw_name;
+ }
+
+ /* Couldn't find a name. Use the empty string. */
+ name = "";
+ tdep->regnames[regno] = xstrdup (name);
+ return name;
}
/* *INDENT-OFF* */
-/* Names of IDT R3041 registers. */
-char *mips_r3041_reg_names[] = {
- "sr", "lo", "hi", "bad", "cause","pc",
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
- "fsr", "fir", "",/*"fp"*/ "",
+
+/* Names of tx39 embedded registers. */
+
+char *mips_tx39_embed_reg_names[] = {
+ "", "", "", "", "", "", "", "",
+ "", "", "config", "cache", "debug", "depc", "epc", ""
+};
+
+/* Names of IDT R3041 embedded registers. */
+
+char *mips_r3041_embed_reg_names[] = {
"", "", "bus", "ccfg", "", "", "", "",
"", "", "port", "cmp", "", "", "epc", "prid",
};
-/* Names of IDT R3051 registers. */
+/* Names of IDT R3051 embedded registers. */
-char *mips_r3051_reg_names[] = {
- "sr", "lo", "hi", "bad", "cause","pc",
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
- "fsr", "fir", ""/*"fp"*/, "",
+char *mips_r3051_embed_reg_names[] = {
"inx", "rand", "elo", "", "ctxt", "", "", "",
"", "", "ehi", "", "", "", "epc", "prid",
};
-/* Names of IDT R3081 registers. */
+/* Names of IDT R3081 embedded registers. */
-char *mips_r3081_reg_names[] = {
- "sr", "lo", "hi", "bad", "cause","pc",
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
- "fsr", "fir", ""/*"fp"*/, "",
+char *mips_r3081_embed_reg_names[] = {
"inx", "rand", "elo", "cfg", "ctxt", "", "", "",
"", "", "ehi", "", "", "", "epc", "prid",
};
+#if 0
/* Names of LSI 33k registers. */
+/* Note: kevinb/2003-05-06: These are all of the names following the GPRs.
+ "baddvaddr" is in the position where "pc" would normally appear, so
+ I don't see how this ever could have worked. I've disabled this code
+ until someone who understands it better than I do can take a look... */
+
char *mips_lsi33k_reg_names[] = {
"epc", "hi", "lo", "sr", "cause","badvaddr",
"dcic", "bpc", "bda", "", "", "", "", "",
@@ -461,17 +552,21 @@ char *mips_lsi33k_reg_names[] = {
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
};
+#endif
struct {
char *name;
char **regnames;
} mips_processor_type_table[] = {
- { "generic", mips_generic_reg_names },
- { "r3041", mips_r3041_reg_names },
- { "r3051", mips_r3051_reg_names },
- { "r3071", mips_r3081_reg_names },
- { "r3081", mips_r3081_reg_names },
- { "lsi33k", mips_lsi33k_reg_names },
+ { "generic", mips_generic_embed_reg_names },
+ { "r3041", mips_r3041_embed_reg_names },
+ { "r3051", mips_r3051_embed_reg_names },
+ { "r3071", mips_r3081_embed_reg_names },
+ { "r3081", mips_r3081_embed_reg_names },
+#if 0
+ { "lsi33k", mips_lsi33k_embed_reg_names },
+#endif
+ { "tx39", mips_tx39_embed_reg_names },
{ NULL, NULL }
};
/* *INDENT-ON* */
@@ -531,126 +626,119 @@ mips_print_extra_frame_info (struct fram
static int mips64_transfers_32bit_regs_p = 0;
-static int
-mips_register_raw_size (int reg_nr)
-{
- if (mips64_transfers_32bit_regs_p)
- return REGISTER_VIRTUAL_SIZE (reg_nr);
- else if (reg_nr >= FP0_REGNUM && reg_nr < FP0_REGNUM + 32
- && FP_REGISTER_DOUBLE)
- /* For MIPS_ABI_N32 (for example) we need 8 byte floating point
- registers. */
- return 8;
- else
- return MIPS_REGSIZE;
-}
-
-/* Convert between RAW and VIRTUAL registers. The RAW register size
- defines the remote-gdb packet. */
-
-static int
-mips_register_convertible (int reg_nr)
-{
- if (mips64_transfers_32bit_regs_p)
- return 0;
- else
- return (REGISTER_RAW_SIZE (reg_nr) > REGISTER_VIRTUAL_SIZE (reg_nr));
-}
-
-static void
-mips_register_convert_to_virtual (int n, struct type *virtual_type,
- char *raw_buf, char *virt_buf)
-{
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
- memcpy (virt_buf,
- raw_buf + (REGISTER_RAW_SIZE (n) - TYPE_LENGTH (virtual_type)),
- TYPE_LENGTH (virtual_type));
- else
- memcpy (virt_buf,
- raw_buf,
- TYPE_LENGTH (virtual_type));
-}
-
-static void
-mips_register_convert_to_raw (struct type *virtual_type, int n,
- char *virt_buf, char *raw_buf)
-{
- memset (raw_buf, 0, REGISTER_RAW_SIZE (n));
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
- memcpy (raw_buf + (REGISTER_RAW_SIZE (n) - TYPE_LENGTH (virtual_type)),
- virt_buf,
- TYPE_LENGTH (virtual_type));
- else
- memcpy (raw_buf,
- virt_buf,
- TYPE_LENGTH (virtual_type));
-}
-
-void
-mips_register_convert_to_type (int regnum, struct type *type, char *buffer)
-{
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
- && REGISTER_RAW_SIZE (regnum) == 4
- && (regnum) >= FP0_REGNUM && (regnum) < FP0_REGNUM + 32
- && TYPE_CODE(type) == TYPE_CODE_FLT
- && TYPE_LENGTH(type) == 8)
- {
- char temp[4];
- memcpy (temp, ((char *)(buffer))+4, 4);
- memcpy (((char *)(buffer))+4, (buffer), 4);
- memcpy (((char *)(buffer)), temp, 4);
- }
-}
-
-void
-mips_register_convert_from_type (int regnum, struct type *type, char *buffer)
-{
-if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
- && REGISTER_RAW_SIZE (regnum) == 4
- && (regnum) >= FP0_REGNUM && (regnum) < FP0_REGNUM + 32
- && TYPE_CODE(type) == TYPE_CODE_FLT
- && TYPE_LENGTH(type) == 8)
- {
- char temp[4];
- memcpy (temp, ((char *)(buffer))+4, 4);
- memcpy (((char *)(buffer))+4, (buffer), 4);
- memcpy (((char *)(buffer)), temp, 4);
- }
-}
-
/* Return the GDB type object for the "standard" data type
of data in register REG.
- Note: kevinb/2002-08-01: The definition below should faithfully
- reproduce the behavior of each of the REGISTER_VIRTUAL_TYPE
- definitions found in config/mips/tm-*.h. I'm concerned about the
- ``FCRCS_REGNUM <= reg && reg <= LAST_EMBED_REGNUM'' clause though.
- In some cases DEPRECATED_FP_REGNUM is in this range, and I doubt
- that this code is correct for the 64-bit case. */
+ As noted below, the types returned in the [0, NUM_REGS) range are
+ constrained by the remote protocol. */
static struct type *
-mips_register_virtual_type (int reg)
+mips_register_type (struct gdbarch *gdbarch, int regno)
{
- if (FP0_REGNUM <= reg && reg < FP0_REGNUM + 32)
+ const struct mips_regnums *raw_regnums = mips_raw_regnums (gdbarch);
+ const struct mips_regnums *cooked_regnums = mips_cooked_regnums (gdbarch);
+
+ gdb_assert (0 <= regno && regno <= NUM_REGS + NUM_PSEUDO_REGS);
+
+ if (regno < NUM_REGS)
{
- /* Floating point registers... */
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
- return builtin_type_ieee_double_big;
+ /* We must be careful with the sizes of these types because
+ they influence the layout of the remote protocol. */
+ if (MIPS_REGSIZE == 4)
+ {
+ /* The type length of each of the types returned in this
+ block is 4. */
+ if (raw_regnums->fp0_regnum <= regno
+ && regno <= raw_regnums->fplast_regnum)
+ {
+ /* It's tempting to make these some kind of floating
+ point type, but it's actually more useful to just
+ print the raw fp registers as ints. The cooked
+ regnums provide access to multiple representations. */
+ return builtin_type_uint32;
+ }
+ else if (regno == raw_regnums->ps_regnum /* SR */
+ || regno == raw_regnums->fcrcs_regnum
+ || regno == raw_regnums->fcrir_regnum
+ || (raw_regnums->first_embed_regnum <= regno
+ && regno <= raw_regnums->last_embed_regnum))
+ return builtin_type_uint32;
+ else
+ return builtin_type_int32;
+ }
+ else if (MIPS_REGSIZE == 8)
+ {
+ /* The type lengths of each of the types returned in this
+ block is 8 except when ``mips64_transfers_32_bit_regs_p''
+ is true. When ``mips64_transfers_32_bit_regs_p'' is true,
+ certain registers are only 4 bytes wide. */
+ if (raw_regnums->fp0_regnum <= regno
+ && regno <= raw_regnums->fplast_regnum)
+ {
+ return builtin_type_uint64;
+ }
+ else if (regno == raw_regnums->ps_regnum /* SR */
+ || regno == raw_regnums->fcrcs_regnum
+ || regno == raw_regnums->fcrir_regnum
+ || (raw_regnums->first_embed_regnum <= regno
+ && regno <= raw_regnums->last_embed_regnum))
+ {
+ if (mips64_transfers_32bit_regs_p)
+ return builtin_type_uint32;
+ else
+ return builtin_type_uint64;
+ }
+ else
+ return builtin_type_uint64;
+ }
else
- return builtin_type_ieee_double_little;
+ {
+ internal_error (__FILE__, __LINE__,
+ "mips_register_type: bad MIPS_REGSIZE value");
+ }
}
- else if (reg == PS_REGNUM /* CR */)
- return builtin_type_uint32;
- else if (FCRCS_REGNUM <= reg && reg <= LAST_EMBED_REGNUM)
- return builtin_type_uint32;
else
{
- /* Everything else...
- Return type appropriate for width of register. */
- if (MIPS_REGSIZE == TYPE_LENGTH (builtin_type_uint64))
- return builtin_type_uint64;
- else
+ /* These registers are pseudo-registers. We are (more or less)
+ free to define them to be whatever we want them to be. */
+ if (cooked_regnums->fp0_regnum <= regno
+ && regno <= cooked_regnums->fplast_regnum)
+ {
+ if (MIPS_FPU_TYPE == MIPS_FPU_SINGLE)
+ {
+ if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+ return mips_type_float_single_register_big;
+ else
+ return mips_type_float_single_register_little;
+ }
+ else if (MIPS_FPU_TYPE == MIPS_FPU_DOUBLE)
+ {
+ if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+ return mips_type_float_double_register_big;
+ else
+ return mips_type_float_double_register_little;
+ }
+ else
+ {
+ /* The other choice is that MIPS_FPU_TYPE is MIPS_FPU_NONE,
+ but that shouldn't happen because fp0_regnum and
+ fplast_regnum should've been set to -1. */
+ internal_error (__FILE__, __LINE__,
+ "mips_register_type: bad MIPS_FPU_TYPE value");
+ }
+ }
+ else if (regno == cooked_regnums->ps_regnum /* SR */
+ || regno == cooked_regnums->fcrcs_regnum
+ || regno == cooked_regnums->fcrir_regnum
+ || (cooked_regnums->first_embed_regnum <= regno
+ && cooked_regnums->last_embed_regnum))
return builtin_type_uint32;
+ else
+ {
+ internal_error (__FILE__, __LINE__,
+ "mips_register_type: unknown pseudo register %d [%s]\n",
+ regno, REGISTER_NAME (regno));
+ }
}
}
@@ -659,7 +747,9 @@ mips_register_virtual_type (int reg)
static CORE_ADDR
mips_read_sp (void)
{
- return read_signed_register (SP_REGNUM);
+ const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
+
+ return read_signed_register (regnums->sp_regnum);
}
/* Should the upper word of 64-bit addresses be zeroed? */
@@ -781,7 +871,9 @@ pc_is_mips16 (bfd_vma memaddr)
static CORE_ADDR
mips_read_pc (ptid_t ptid)
{
- return read_signed_register_pid (PC_REGNUM, ptid);
+ const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
+
+ return read_signed_register_pid (regnums->pc_regnum, ptid);
}
/* This returns the PC of the first inst after the prologue. If we can't
@@ -793,6 +885,7 @@ after_prologue (CORE_ADDR pc,
{
struct symtab_and_line sal;
CORE_ADDR func_addr, func_end;
+ const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
/* Pass cur_frame == 0 to find_proc_desc. We should not attempt
to read the stack pointer from the current machine state, because
@@ -806,7 +899,7 @@ after_prologue (CORE_ADDR pc,
{
/* If function is frameless, then we need to do it the hard way. I
strongly suspect that frameless always means prologueless... */
- if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
+ if (PROC_FRAME_REG (proc_desc) == regnums->sp_regnum
&& PROC_FRAME_OFFSET (proc_desc) == 0)
return 0;
}
@@ -866,6 +959,8 @@ mips32_decode_reg_save (t_inst inst, uns
static void
mips16_decode_reg_save (t_inst inst, unsigned long *gen_mask)
{
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
if ((inst & 0xf800) == 0xd000) /* sw reg,n($sp) */
{
int reg = mips16_to_32_reg[(inst & 0x700) >> 8];
@@ -878,7 +973,7 @@ mips16_decode_reg_save (t_inst inst, uns
}
else if ((inst & 0xff00) == 0x6200 /* sw $ra,n($sp) */
|| (inst & 0xff00) == 0xfa00) /* sd $ra,n($sp) */
- *gen_mask |= (1 << RA_REGNUM);
+ *gen_mask |= (1 << (regnums->ra_regnum - regnums->zero_regnum));
}
@@ -943,6 +1038,8 @@ mips32_next_pc (CORE_ADDR pc)
{
unsigned long inst;
int op;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
inst = mips_fetch_instruction (pc);
if ((inst & 0xe0000000) != 0) /* Not a special, jump or branch instruction */
{
@@ -969,7 +1066,7 @@ mips32_next_pc (CORE_ADDR pc)
{
int tf = itype_rt (inst) & 0x01;
int cnum = itype_rt (inst) >> 2;
- int fcrcs = read_signed_register (FCRCS_REGNUM);
+ int fcrcs = read_signed_register (regnums->fcrcs_regnum);
int cond = ((fcrcs >> 24) & 0x0e) | ((fcrcs >> 23) & 0x01);
if (((cond >> cnum) & 0x01) == tf)
@@ -1420,6 +1517,8 @@ mips_find_saved_regs (struct frame_info
unsigned long gen_mask, float_mask;
mips_extra_func_info_t proc_desc;
t_inst inst;
+ const struct mips_regnums *raw_regnums = mips_raw_regnums (current_gdbarch);
+ const struct mips_regnums *cooked_regnums = mips_cooked_regnums (current_gdbarch);
frame_saved_regs_zalloc (fci);
@@ -1453,9 +1552,9 @@ mips_find_saved_regs (struct frame_info
{
reg_position = get_frame_base (fci) + SIGFRAME_FPREGSAVE_OFF
+ ireg * SIGFRAME_REG_SIZE;
- get_frame_saved_regs (fci)[FP0_REGNUM + ireg] = reg_position;
+ get_frame_saved_regs (fci)[raw_regnums->fp0_regnum + ireg] = reg_position;
}
- get_frame_saved_regs (fci)[PC_REGNUM] = get_frame_base (fci) + SIGFRAME_PC_OFF;
+ get_frame_saved_regs (fci)[raw_regnums->pc_regnum] = get_frame_base (fci) + SIGFRAME_PC_OFF;
return;
}
@@ -1581,11 +1680,25 @@ mips_find_saved_regs (struct frame_info
for (ireg = MIPS_NUMREGS - 1; float_mask; --ireg, float_mask <<= 1)
if (float_mask & 0x80000000)
{
- get_frame_saved_regs (fci)[FP0_REGNUM + ireg] = reg_position;
+ get_frame_saved_regs (fci)[raw_regnums->fp0_regnum + ireg]
+ = reg_position;
+
+ /* Now take care of the cooked register number. */
+ if (!FP_REGISTER_DOUBLE && MIPS_FPU_TYPE == MIPS_FPU_DOUBLE)
+ {
+ if ((ireg & 1) == 0)
+ get_frame_saved_regs (fci)[cooked_regnums->fp0_regnum + ireg / 2]
+ = reg_position;
+ }
+ else
+ get_frame_saved_regs (fci)[cooked_regnums->fp0_regnum + ireg]
+ = reg_position;
+
reg_position -= MIPS_SAVED_REGSIZE;
}
- get_frame_saved_regs (fci)[PC_REGNUM] = get_frame_saved_regs (fci)[RA_REGNUM];
+ get_frame_saved_regs (fci)[raw_regnums->pc_regnum]
+ = get_frame_saved_regs (fci)[raw_regnums->ra_regnum];
}
/* Set up the 'saved_regs' array. This is a data structure containing
@@ -1598,11 +1711,13 @@ mips_find_saved_regs (struct frame_info
static void
mips_frame_init_saved_regs (struct frame_info *frame)
{
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
if (get_frame_saved_regs (frame) == NULL)
{
mips_find_saved_regs (frame);
}
- get_frame_saved_regs (frame)[SP_REGNUM] = get_frame_base (frame);
+ get_frame_saved_regs (frame)[regnums->sp_regnum] = get_frame_base (frame);
}
static CORE_ADDR
@@ -1697,10 +1812,11 @@ mips_software_single_step (enum target_s
typedef char binsn_quantum[BREAKPOINT_MAX];
static binsn_quantum break_mem;
CORE_ADDR pc;
+ const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
if (insert_breakpoints_p)
{
- pc = read_register (PC_REGNUM);
+ pc = read_register (regnums->pc_regnum);
next_pc = mips_next_pc (pc);
target_insert_breakpoint (next_pc, break_mem);
@@ -1729,15 +1845,17 @@ mips_frame_saved_pc (struct frame_info *
{
CORE_ADDR saved_pc;
mips_extra_func_info_t proc_desc = get_frame_extra_info (frame)->proc_desc;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
/* We have to get the saved pc from the sigcontext
if it is a signal handler frame. */
- int pcreg = (get_frame_type (frame) == SIGTRAMP_FRAME) ? PC_REGNUM
- : (proc_desc ? PROC_PC_REG (proc_desc) : RA_REGNUM);
+ int pcreg = (get_frame_type (frame) == SIGTRAMP_FRAME) ? regnums->pc_regnum
+ : (proc_desc ? PROC_PC_REG (proc_desc) : regnums->ra_regnum);
if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (frame), 0, 0))
{
LONGEST tmp;
- frame_unwind_signed_register (frame, PC_REGNUM, &tmp);
+ frame_unwind_signed_register (frame, regnums->pc_regnum, &tmp);
saved_pc = tmp;
}
else if (proc_desc && PROC_DESC_IS_DUMMY (proc_desc))
@@ -1933,6 +2051,7 @@ mips16_heuristic_proc_desc (CORE_ADDR st
unsigned inst = 0; /* current instruction */
unsigned entry_inst = 0; /* the entry instruction */
int reg, offset;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
PROC_FRAME_OFFSET (&temp_proc_desc) = 0; /* size of stack frame */
PROC_FRAME_ADJUST (&temp_proc_desc) = 0; /* offset of FP from SP */
@@ -1974,14 +2093,14 @@ mips16_heuristic_proc_desc (CORE_ADDR st
else if ((inst & 0xff00) == 0x6200) /* sw $ra,n($sp) */
{
offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
- PROC_REG_MASK (&temp_proc_desc) |= (1 << RA_REGNUM);
- set_reg_offset (RA_REGNUM, sp + offset);
+ PROC_REG_MASK (&temp_proc_desc) |= (1 << regnums->ra_regnum);
+ set_reg_offset (regnums->ra_regnum, sp + offset);
}
else if ((inst & 0xff00) == 0xfa00) /* sd $ra,n($sp) */
{
offset = mips16_get_imm (prev_inst, inst, 8, 8, 0);
- PROC_REG_MASK (&temp_proc_desc) |= (1 << RA_REGNUM);
- set_reg_offset (RA_REGNUM, sp + offset);
+ PROC_REG_MASK (&temp_proc_desc) |= (1 << regnums->ra_regnum);
+ set_reg_offset (regnums->ra_regnum, sp + offset);
}
else if (inst == 0x673d) /* move $s1, $sp */
{
@@ -2045,8 +2164,8 @@ mips16_heuristic_proc_desc (CORE_ADDR st
offset = -4;
if (entry_inst & 0x20)
{
- PROC_REG_MASK (&temp_proc_desc) |= 1 << RA_REGNUM;
- set_reg_offset (RA_REGNUM, sp + offset);
+ PROC_REG_MASK (&temp_proc_desc) |= 1 << regnums->ra_regnum;
+ set_reg_offset (regnums->ra_regnum, sp + offset);
offset -= MIPS_SAVED_REGSIZE;
}
@@ -2066,6 +2185,8 @@ mips32_heuristic_proc_desc (CORE_ADDR st
{
CORE_ADDR cur_pc;
CORE_ADDR frame_addr = 0; /* Value of $r30. Used by gcc for frame-pointer */
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
restart:
temp_saved_regs = xrealloc (temp_saved_regs, SIZEOF_FRAME_SAVED_REGS);
memset (temp_saved_regs, '\0', SIZEOF_FRAME_SAVED_REGS);
@@ -2114,7 +2235,7 @@ restart:
/* Old gcc frame, r30 is virtual frame pointer. */
if ((long) low_word != PROC_FRAME_OFFSET (&temp_proc_desc))
frame_addr = sp + low_word;
- else if (PROC_FRAME_REG (&temp_proc_desc) == SP_REGNUM)
+ else if (PROC_FRAME_REG (&temp_proc_desc) == regnums->sp_regnum)
{
unsigned alloca_adjust;
PROC_FRAME_REG (&temp_proc_desc) = 30;
@@ -2137,7 +2258,7 @@ restart:
else if (inst == 0x03A0F021 || inst == 0x03a0f025 || inst == 0x03a0f02d)
{
/* New gcc frame, virtual frame pointer is at r30 + frame_size. */
- if (PROC_FRAME_REG (&temp_proc_desc) == SP_REGNUM)
+ if (PROC_FRAME_REG (&temp_proc_desc) == regnums->sp_regnum)
{
unsigned alloca_adjust;
PROC_FRAME_REG (&temp_proc_desc) = 30;
@@ -2167,9 +2288,10 @@ heuristic_proc_desc (CORE_ADDR start_pc,
struct frame_info *next_frame, int cur_frame)
{
CORE_ADDR sp;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
if (cur_frame)
- sp = read_next_frame_reg (next_frame, SP_REGNUM);
+ sp = read_next_frame_reg (next_frame, regnums->sp_regnum);
else
sp = 0;
@@ -2179,8 +2301,8 @@ heuristic_proc_desc (CORE_ADDR start_pc,
temp_saved_regs = xrealloc (temp_saved_regs, SIZEOF_FRAME_SAVED_REGS);
memset (temp_saved_regs, '\0', SIZEOF_FRAME_SAVED_REGS);
PROC_LOW_ADDR (&temp_proc_desc) = start_pc;
- PROC_FRAME_REG (&temp_proc_desc) = SP_REGNUM;
- PROC_PC_REG (&temp_proc_desc) = RA_REGNUM;
+ PROC_FRAME_REG (&temp_proc_desc) = regnums->sp_regnum;
+ PROC_PC_REG (&temp_proc_desc) = regnums->ra_regnum;
if (start_pc + 200 < limit_pc)
limit_pc = start_pc + 200;
@@ -2455,6 +2577,7 @@ mips_frame_chain (struct frame_info *fra
mips_extra_func_info_t proc_desc;
CORE_ADDR tmp;
CORE_ADDR saved_pc = DEPRECATED_FRAME_SAVED_PC (frame);
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
if (saved_pc == 0 || inside_entry_file (saved_pc))
return 0;
@@ -2482,7 +2605,7 @@ mips_frame_chain (struct frame_info *fra
/* If no frame pointer and frame size is zero, we must be at end
of stack (or otherwise hosed). If we don't check frame size,
we loop forever if we see a zero size frame. */
- if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
+ if (PROC_FRAME_REG (proc_desc) == regnums->sp_regnum
&& PROC_FRAME_OFFSET (proc_desc) == 0
/* The previous frame from a sigtramp frame might be frameless
and have frame size zero. */
@@ -2500,6 +2623,7 @@ mips_init_extra_frame_info (int fromleaf
{
int regnum;
mips_extra_func_info_t proc_desc;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
if (get_frame_type (fci) == DUMMY_FRAME)
return;
@@ -2528,7 +2652,8 @@ mips_init_extra_frame_info (int fromleaf
interrupted by a signal at it's very start. */
if (get_frame_pc (fci) == PROC_LOW_ADDR (proc_desc)
&& !PROC_DESC_IS_DUMMY (proc_desc))
- deprecated_update_frame_base_hack (fci, read_next_frame_reg (get_next_frame (fci), SP_REGNUM));
+ deprecated_update_frame_base_hack (fci,
+ read_next_frame_reg (get_next_frame (fci), regnums->sp_regnum));
else if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fci), 0, 0))
/* Do not ``fix'' fci->frame. It will have the value of the
generic dummy frame's top-of-stack (since the draft
@@ -2557,25 +2682,28 @@ mips_init_extra_frame_info (int fromleaf
{
frame_saved_regs_zalloc (fci);
memcpy (get_frame_saved_regs (fci), temp_saved_regs, SIZEOF_FRAME_SAVED_REGS);
- get_frame_saved_regs (fci)[PC_REGNUM]
- = get_frame_saved_regs (fci)[RA_REGNUM];
+ get_frame_saved_regs (fci)[regnums->pc_regnum]
+ = get_frame_saved_regs (fci)[regnums->ra_regnum];
/* Set value of previous frame's stack pointer. Remember that
saved_regs[SP_REGNUM] is special in that it contains the
value of the stack pointer register. The other saved_regs
values are addresses (in the inferior) at which a given
register's value may be found. */
- get_frame_saved_regs (fci)[SP_REGNUM] = get_frame_base (fci);
+ get_frame_saved_regs (fci)[regnums->sp_regnum] = get_frame_base (fci);
}
}
/* hack: if argument regs are saved, guess these contain args */
/* assume we can't tell how many args for now */
get_frame_extra_info (fci)->num_args = -1;
- for (regnum = MIPS_LAST_ARG_REGNUM; regnum >= A0_REGNUM; regnum--)
+ for (regnum = regnums->last_arg_regnum;
+ regnum >= regnums->a0_regnum;
+ regnum--)
{
if (PROC_REG_MASK (proc_desc) & (1 << regnum))
{
- get_frame_extra_info (fci)->num_args = regnum - A0_REGNUM + 1;
+ get_frame_extra_info (fci)->num_args
+ = regnum - regnums->a0_regnum + 1;
break;
}
}
@@ -2678,6 +2806,7 @@ mips_eabi_push_arguments (int nargs,
int argnum;
int len = 0;
int stack_offset = 0;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
/* First ensure that the stack and structure return address (if any)
are properly aligned. The stack has to be at least 64-bit
@@ -2702,8 +2831,8 @@ mips_eabi_push_arguments (int nargs,
paddr_nz (sp), ROUND_UP (len, 16));
/* Initialize the integer and float register pointers. */
- argreg = A0_REGNUM;
- float_argreg = FPA0_REGNUM;
+ argreg = regnums->a0_regnum;
+ float_argreg = regnums->first_fp_arg_regnum;
/* The struct_return pointer occupies the first parameter-passing reg. */
if (struct_return)
@@ -2772,7 +2901,7 @@ mips_eabi_push_arguments (int nargs,
point value into an FP register instead of pushing it onto the
stack. */
if (fp_register_arg_p (typecode, arg_type)
- && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
+ && float_argreg <= regnums->last_fp_arg_regnum)
{
if (!FP_REGISTER_DOUBLE && len == 8)
{
@@ -2832,7 +2961,7 @@ mips_eabi_push_arguments (int nargs,
partial_len);
/* Write this portion of the argument to the stack. */
- if (argreg > MIPS_LAST_ARG_REGNUM
+ if (argreg > regnums->last_arg_regnum
|| odd_sized_struct
|| fp_register_arg_p (typecode, arg_type))
{
@@ -2883,7 +3012,7 @@ mips_eabi_push_arguments (int nargs,
arguments will not. */
/* Write this portion of the argument to a general
purpose register. */
- if (argreg <= MIPS_LAST_ARG_REGNUM
+ if (argreg <= regnums->last_arg_regnum
&& !fp_register_arg_p (typecode, arg_type))
{
LONGEST regval = extract_unsigned_integer (val, partial_len);
@@ -2931,6 +3060,7 @@ mips_n32n64_push_arguments (int nargs,
int argnum;
int len = 0;
int stack_offset = 0;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
/* First ensure that the stack and structure return address (if any)
are properly aligned. The stack has to be at least 64-bit
@@ -2953,8 +3083,8 @@ mips_n32n64_push_arguments (int nargs,
paddr_nz (sp), ROUND_UP (len, 16));
/* Initialize the integer and float register pointers. */
- argreg = A0_REGNUM;
- float_argreg = FPA0_REGNUM;
+ argreg = regnums->a0_regnum;
+ float_argreg = regnums->first_fp_arg_regnum;
/* The struct_return pointer occupies the first parameter-passing reg. */
if (struct_return)
@@ -2986,7 +3116,7 @@ mips_n32n64_push_arguments (int nargs,
val = (char *) VALUE_CONTENTS (arg);
if (fp_register_arg_p (typecode, arg_type)
- && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
+ && float_argreg <= regnums->last_fp_arg_regnum)
{
/* This is a floating point value that fits entirely
in a single register. */
@@ -3029,7 +3159,7 @@ mips_n32n64_push_arguments (int nargs,
partial_len);
/* Write this portion of the argument to the stack. */
- if (argreg > MIPS_LAST_ARG_REGNUM
+ if (argreg > regnums->last_arg_regnum
|| odd_sized_struct
|| fp_register_arg_p (typecode, arg_type))
{
@@ -3076,7 +3206,7 @@ mips_n32n64_push_arguments (int nargs,
arguments will not. */
/* Write this portion of the argument to a general
purpose register. */
- if (argreg <= MIPS_LAST_ARG_REGNUM
+ if (argreg <= regnums->last_arg_regnum
&& !fp_register_arg_p (typecode, arg_type))
{
LONGEST regval = extract_unsigned_integer (val, partial_len);
@@ -3153,6 +3283,7 @@ mips_o32_push_arguments (int nargs,
int argnum;
int len = 0;
int stack_offset = 0;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
/* First ensure that the stack and structure return address (if any)
are properly aligned. The stack has to be at least 64-bit
@@ -3175,8 +3306,8 @@ mips_o32_push_arguments (int nargs,
paddr_nz (sp), ROUND_UP (len, 16));
/* Initialize the integer and float register pointers. */
- argreg = A0_REGNUM;
- float_argreg = FPA0_REGNUM;
+ argreg = regnums->a0_regnum;
+ float_argreg = regnums->first_fp_arg_regnum;
/* The struct_return pointer occupies the first parameter-passing reg. */
if (struct_return)
@@ -3231,7 +3362,7 @@ mips_o32_push_arguments (int nargs,
because those registers are normally skipped. */
if (fp_register_arg_p (typecode, arg_type)
- && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
+ && float_argreg <= regnums->last_fp_arg_regnum)
{
if (!FP_REGISTER_DOUBLE && len == 8)
{
@@ -3318,7 +3449,7 @@ mips_o32_push_arguments (int nargs,
partial_len);
/* Write this portion of the argument to the stack. */
- if (argreg > MIPS_LAST_ARG_REGNUM
+ if (argreg > regnums->last_arg_regnum
|| odd_sized_struct
|| fp_register_arg_p (typecode, arg_type))
{
@@ -3365,7 +3496,7 @@ mips_o32_push_arguments (int nargs,
arguments will not. */
/* Write this portion of the argument to a general
purpose register. */
- if (argreg <= MIPS_LAST_ARG_REGNUM
+ if (argreg <= regnums->last_arg_regnum
&& !fp_register_arg_p (typecode, arg_type))
{
LONGEST regval = extract_signed_integer (val, partial_len);
@@ -3413,7 +3544,7 @@ mips_o32_push_arguments (int nargs,
/* Prevent subsequent floating point arguments from
being passed in floating point registers. */
- float_argreg = MIPS_LAST_FP_ARG_REGNUM + 1;
+ float_argreg = regnums->last_fp_arg_regnum + 1;
}
len -= partial_len;
@@ -3452,6 +3583,7 @@ mips_o64_push_arguments (int nargs,
int argnum;
int len = 0;
int stack_offset = 0;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
/* First ensure that the stack and structure return address (if any)
are properly aligned. The stack has to be at least 64-bit
@@ -3474,8 +3606,8 @@ mips_o64_push_arguments (int nargs,
paddr_nz (sp), ROUND_UP (len, 16));
/* Initialize the integer and float register pointers. */
- argreg = A0_REGNUM;
- float_argreg = FPA0_REGNUM;
+ argreg = regnums->a0_regnum;
+ float_argreg = regnums->first_fp_arg_regnum;
/* The struct_return pointer occupies the first parameter-passing reg. */
if (struct_return)
@@ -3530,7 +3662,7 @@ mips_o64_push_arguments (int nargs,
because those registers are normally skipped. */
if (fp_register_arg_p (typecode, arg_type)
- && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
+ && float_argreg <= regnums->last_fp_arg_regnum)
{
if (!FP_REGISTER_DOUBLE && len == 8)
{
@@ -3617,7 +3749,7 @@ mips_o64_push_arguments (int nargs,
partial_len);
/* Write this portion of the argument to the stack. */
- if (argreg > MIPS_LAST_ARG_REGNUM
+ if (argreg > regnums->last_arg_regnum
|| odd_sized_struct
|| fp_register_arg_p (typecode, arg_type))
{
@@ -3664,7 +3796,7 @@ mips_o64_push_arguments (int nargs,
arguments will not. */
/* Write this portion of the argument to a general
purpose register. */
- if (argreg <= MIPS_LAST_ARG_REGNUM
+ if (argreg <= regnums->last_arg_regnum
&& !fp_register_arg_p (typecode, arg_type))
{
LONGEST regval = extract_signed_integer (val, partial_len);
@@ -3712,7 +3844,7 @@ mips_o64_push_arguments (int nargs,
/* Prevent subsequent floating point arguments from
being passed in floating point registers. */
- float_argreg = MIPS_LAST_FP_ARG_REGNUM + 1;
+ float_argreg = regnums->last_fp_arg_regnum + 1;
}
len -= partial_len;
@@ -3740,9 +3872,11 @@ mips_o64_push_arguments (int nargs,
static CORE_ADDR
mips_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
{
+ const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
+
/* Set the return address register to point to the entry
point of the program, where a breakpoint lies in wait. */
- write_register (RA_REGNUM, CALL_DUMMY_ADDRESS ());
+ write_register (regnums->ra_regnum, CALL_DUMMY_ADDRESS ());
return sp;
}
@@ -3753,6 +3887,7 @@ mips_pop_frame (void)
struct frame_info *frame = get_current_frame ();
CORE_ADDR new_sp = get_frame_base (frame);
mips_extra_func_info_t proc_desc;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (frame), 0, 0))
{
@@ -3762,17 +3897,18 @@ mips_pop_frame (void)
}
proc_desc = get_frame_extra_info (frame)->proc_desc;
- write_register (PC_REGNUM, DEPRECATED_FRAME_SAVED_PC (frame));
+ write_register (regnums->pc_regnum, DEPRECATED_FRAME_SAVED_PC (frame));
if (get_frame_saved_regs (frame) == NULL)
DEPRECATED_FRAME_INIT_SAVED_REGS (frame);
for (regnum = 0; regnum < NUM_REGS; regnum++)
- if (regnum != SP_REGNUM && regnum != PC_REGNUM
+ if (regnum != regnums->sp_regnum && regnum != regnums->pc_regnum
&& get_frame_saved_regs (frame)[regnum])
{
/* Floating point registers must not be sign extended,
- in case MIPS_SAVED_REGSIZE = 4 but sizeof (FP0_REGNUM) == 8. */
+ in case MIPS_SAVED_REGSIZE = 4 but
+ REGISTER_RAW_SIZE (regnums->fp0_regnum)) == 8. */
- if (FP0_REGNUM <= regnum && regnum < FP0_REGNUM + 32)
+ if (regnums->fp0_regnum <= regnum && regnum < regnums->fplast_regnum)
write_register (regnum,
read_memory_unsigned_integer (get_frame_saved_regs (frame)[regnum],
MIPS_SAVED_REGSIZE));
@@ -3782,7 +3918,7 @@ mips_pop_frame (void)
MIPS_SAVED_REGSIZE));
}
- write_register (SP_REGNUM, new_sp);
+ write_register (regnums->sp_regnum, new_sp);
flush_cached_frames ();
if (proc_desc && PROC_DESC_IS_DUMMY (proc_desc))
@@ -3807,14 +3943,14 @@ mips_pop_frame (void)
xfree (pi_ptr);
- write_register (HI_REGNUM,
+ write_register (regnums->hi_regnum,
read_memory_integer (new_sp - 2 * MIPS_SAVED_REGSIZE,
MIPS_SAVED_REGSIZE));
- write_register (LO_REGNUM,
+ write_register (regnums->lo_regnum,
read_memory_integer (new_sp - 3 * MIPS_SAVED_REGSIZE,
MIPS_SAVED_REGSIZE));
if (MIPS_FPU_TYPE != MIPS_FPU_NONE)
- write_register (FCRCS_REGNUM,
+ write_register (regnums->fcrcs_regnum,
read_memory_integer (new_sp - 4 * MIPS_SAVED_REGSIZE,
MIPS_SAVED_REGSIZE));
}
@@ -3824,9 +3960,58 @@ static void
mips_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
struct value **args, struct type *type, int gcc_p)
{
- write_register(T9_REGNUM, fun);
+ const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
+
+ write_register(regnums->t9_regnum, fun);
+}
+
+/* mips register groups. We add "raw" to the normal groups. */
+
+static struct reggroup *mips_raw_reggroup;
+
+static void
+mips_init_reggroups (void)
+{
+ mips_raw_reggroup = reggroup_new ("raw", USER_REGGROUP);
+}
+
+static void
+mips_add_reggroups (struct gdbarch *gdbarch)
+{
+ reggroup_add (gdbarch, mips_raw_reggroup);
+ reggroup_add (gdbarch, general_reggroup);
+ reggroup_add (gdbarch, float_reggroup);
+ reggroup_add (gdbarch, all_reggroup);
+ reggroup_add (gdbarch, save_reggroup);
+ reggroup_add (gdbarch, restore_reggroup);
+ reggroup_add (gdbarch, vector_reggroup);
+ reggroup_add (gdbarch, system_reggroup);
+}
+
+static int
+mips_register_reggroup_p (struct gdbarch *gdbarch, int regno,
+ struct reggroup *group)
+{
+ int raw_p, float_p;
+ const char *regname;
+ const struct mips_regnums *cooked_regnums = mips_cooked_regnums (gdbarch);
+
+ regname = REGISTER_NAME (regno);
+
+ raw_p = (strncmp (regname, "raw_", 4) == 0);
+ float_p = (cooked_regnums->fp0_regnum <= regno
+ && regno <= cooked_regnums->fplast_regnum);
+
+ if (group == mips_raw_reggroup)
+ return raw_p;
+ if (group == float_reggroup)
+ return float_p;
+ if (group == general_reggroup)
+ return !float_p && !raw_p && *regname != '\0';
+ return default_register_reggroup_p (gdbarch, regno, group);
}
+
/* Floating point register management.
Background: MIPS1 & 2 fp registers are 32 bits wide. To support
@@ -3875,6 +4060,346 @@ mips_double_register_type (void)
return builtin_type_ieee_double_little;
}
+static int
+mips_is_floating_point_register (int regnum)
+{
+ return gdbarch_register_reggroup_p (current_gdbarch, regnum, float_reggroup);
+}
+
+static int
+mips_is_raw_register (int regnum)
+{
+ return gdbarch_register_reggroup_p (current_gdbarch, regnum, mips_raw_reggroup);
+}
+
+static int
+mips_is_general_purpose_register (int regnum)
+{
+ return gdbarch_register_reggroup_p (current_gdbarch, regnum, general_reggroup);
+}
+
+static struct type *
+build_mips_type_float_double_register_big (void)
+{
+ /* Construct a type for mips floating point registers. The type we're
+ building is (roughly) this: */
+#if 0
+ union __gdb_mips_type_float_double_register_big
+ {
+ uint64_t i;
+ float f;
+ double d;
+ };
+#endif
+
+ struct type *t;
+ struct field *f;
+
+ t = init_composite_type ("__gdb_mips_type_float_double_register_big",
+ TYPE_CODE_UNION);
+ append_composite_type_field (t, "i", builtin_type_uint64);
+ append_composite_type_field (t, "f", builtin_type_ieee_single_big);
+ f = &(TYPE_FIELDS (t))[TYPE_NFIELDS (t) - 1];
+ FIELD_BITPOS (f[0]) = 32;
+ append_composite_type_field (t, "d", builtin_type_ieee_double_big);
+
+ TYPE_NAME (t) = "mips_type_float_double_register_big";
+ return t;
+}
+
+static struct type *
+build_mips_type_float_double_register_little (void)
+{
+ /* Construct a type for mips floating point registers. The type we're
+ building is (roughly) this: */
+#if 0
+ union __gdb_mips_type_float_double_register_little
+ {
+ uint64_t i;
+ float f;
+ double d;
+ };
+#endif
+
+ struct type *t;
+
+ t = init_composite_type ("__gdb_mips_type_float_double_register_little",
+ TYPE_CODE_UNION);
+ append_composite_type_field (t, "i", builtin_type_uint64);
+ append_composite_type_field (t, "f", builtin_type_ieee_single_little);
+ append_composite_type_field (t, "d", builtin_type_ieee_double_little);
+ TYPE_NAME (t) = "mips_type_float_double_register_little";
+ return t;
+}
+
+static struct type *
+build_mips_type_float_single_register_big (void)
+{
+ /* Construct a type for mips single-precision floating point registers.
+ The type we're building is (roughly) this: */
+#if 0
+ union __gdb_mips_type_float_single_register_big
+ {
+ uint32_t i;
+ float f;
+ };
+#endif
+
+ struct type *t;
+
+ t = init_composite_type ("__gdb_mips_type_float_single_register_big",
+ TYPE_CODE_UNION);
+ append_composite_type_field (t, "i", builtin_type_uint32);
+ append_composite_type_field (t, "f", builtin_type_ieee_single_big);
+ TYPE_NAME (t) = "mips_type_float_single_register_big";
+ return t;
+}
+
+static struct type *
+build_mips_type_float_single_register_little (void)
+{
+ /* Construct a type for mips single-precision floating point registers.
+ The type we're building is (roughly) this: */
+#if 0
+ union __gdb_mips_type_float_single_register_little
+ {
+ uint32_t i;
+ float f;
+ };
+#endif
+
+ struct type *t;
+
+ t = init_composite_type ("__gdb_mips_type_float_single_register_little",
+ TYPE_CODE_UNION);
+ append_composite_type_field (t, "i", builtin_type_uint32);
+ append_composite_type_field (t, "f", builtin_type_ieee_single_little);
+ TYPE_NAME (t) = "mips_type_float_single_register_little";
+ return t;
+}
+
+/* Given a cooked regnum, find the corresponding raw regnum which should
+ be used to determine the value of the cooked register. (Or vice versa
+ if writing to the cooked register...) Returns the cooked register number
+ or -1 if there is no (known) corresponding raw register number.
+
+ Note that this could be sped up by caching the results in the gdbarch_tdep
+ struct. */
+
+static int
+cooked_regnum_to_raw_regnum (struct gdbarch *gdbarch, int cooked_regno)
+{
+ const struct mips_regnums *raw_regnums = mips_raw_regnums (gdbarch);
+ const struct mips_regnums *cooked_regnums = mips_cooked_regnums (gdbarch);
+ int raw_regno;
+
+ if (cooked_regnums->fp0_regnum <= cooked_regno
+ && cooked_regno <= cooked_regnums->fplast_regnum)
+ {
+ if (cooked_regnums->fplast_regnum - cooked_regnums->fp0_regnum + 1 == 16)
+ {
+ raw_regno = 2 * (cooked_regno - cooked_regnums->fp0_regnum)
+ + raw_regnums->fp0_regnum;
+ }
+ else
+ {
+ gdb_assert (cooked_regnums->fplast_regnum - cooked_regnums->fp0_regnum
+ == raw_regnums->fplast_regnum - raw_regnums->fp0_regnum);
+
+ raw_regno = raw_regnums->fp0_regnum
+ + (cooked_regno - cooked_regnums->fp0_regnum);
+ }
+ }
+ else if (cooked_regno == cooked_regnums->ps_regnum)
+ {
+ gdb_assert (raw_regnums->ps_regnum != -1);
+ raw_regno = raw_regnums->ps_regnum;
+ }
+ else if (cooked_regno == cooked_regnums->fcrcs_regnum)
+ {
+ gdb_assert (raw_regnums->fcrcs_regnum != -1);
+ raw_regno = raw_regnums->fcrcs_regnum;
+ }
+ else if (cooked_regno == cooked_regnums->fcrir_regnum)
+ {
+ gdb_assert (raw_regnums->fcrir_regnum != -1);
+ raw_regno = raw_regnums->fcrir_regnum;
+ }
+ else if (cooked_regnums->first_embed_regnum <= cooked_regno
+ && cooked_regno <= cooked_regnums->last_embed_regnum)
+ {
+ gdb_assert (raw_regnums->first_embed_regnum != -1
+ && (cooked_regnums->last_embed_regnum
+ - cooked_regnums->first_embed_regnum
+ == raw_regnums->last_embed_regnum
+ - raw_regnums->first_embed_regnum));
+ raw_regno = raw_regnums->first_embed_regnum
+ + (cooked_regno - cooked_regnums->first_embed_regnum);
+ }
+ else
+ {
+ raw_regno = -1;
+ }
+
+ return raw_regno;
+}
+
+static void
+mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+ int cooked_regno, void *buffer)
+{
+ const struct mips_regnums *raw_regnums = mips_raw_regnums (gdbarch);
+ const struct mips_regnums *cooked_regnums = mips_cooked_regnums (gdbarch);
+ int raw_regno;
+ char *raw_buf;
+ int raw_size, raw_offset, cooked_size;
+
+
+ raw_regno = cooked_regnum_to_raw_regnum (gdbarch, cooked_regno);
+ if (raw_regno == -1)
+ {
+ warning ("mips_pseudo_register_read: Don't know how to read "
+ "register %d [%s]", cooked_regno, REGISTER_NAME (cooked_regno));
+ memset (buffer, 0, REGISTER_RAW_SIZE (cooked_regno));
+ return;
+ }
+
+ cooked_size = REGISTER_VIRTUAL_SIZE (cooked_regno);
+ raw_size = REGISTER_VIRTUAL_SIZE (raw_regno);
+ raw_buf = alloca (raw_size);
+
+ if (raw_regnums->fp0_regnum <= raw_regno
+ && raw_regno <= raw_regnums->fplast_regnum
+ && !FP_REGISTER_DOUBLE && MIPS_FPU_TYPE == MIPS_FPU_DOUBLE)
+ {
+ int cooked_offset0, cooked_offset1;
+
+ gdb_assert (cooked_size == 8
+ && cooked_regnums->fplast_regnum
+ - cooked_regnums->fp0_regnum + 1 == 16);
+
+ if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+ {
+ if (raw_size == 8)
+ raw_offset = 4;
+ else
+ raw_offset = 0;
+ cooked_offset0 = 4;
+ cooked_offset1 = 0;
+ }
+ else
+ {
+ raw_offset = 0;
+ cooked_offset0 = 0;
+ cooked_offset1 = 4;
+ }
+
+ regcache_raw_read (regcache, raw_regno, raw_buf);
+ memcpy ((char *) buffer + cooked_offset0, raw_buf + raw_offset, 4);
+ regcache_raw_read (regcache, raw_regno + 1, raw_buf);
+ memcpy ((char *) buffer + cooked_offset1, raw_buf + raw_offset, 4);
+ }
+ else
+ {
+ if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+ raw_offset = raw_size - cooked_size;
+ else
+ raw_offset = 0;
+
+ gdb_assert (raw_offset >= 0);
+
+ regcache_raw_read (regcache, raw_regno, raw_buf);
+ memcpy (buffer, raw_buf + raw_offset, cooked_size);
+ }
+}
+
+static void
+mips_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+ int cooked_regno, const void *buffer)
+{
+ const struct mips_regnums *raw_regnums = mips_raw_regnums (gdbarch);
+ const struct mips_regnums *cooked_regnums = mips_cooked_regnums (gdbarch);
+ int raw_regno;
+ char *raw_buf;
+ int raw_size, raw_offset, cooked_size;
+
+ raw_regno = cooked_regnum_to_raw_regnum (gdbarch, cooked_regno);
+ if (raw_regno == -1)
+ {
+ warning ("mips_pseudo_register_write: Don't know how to write "
+ "register %d [%s]", cooked_regno, REGISTER_NAME (cooked_regno));
+ return;
+ }
+
+ cooked_size = REGISTER_VIRTUAL_SIZE (cooked_regno);
+ raw_size = REGISTER_VIRTUAL_SIZE (raw_regno);
+ raw_buf = alloca (raw_size);
+
+ if (raw_regnums->fp0_regnum <= raw_regno
+ && raw_regno <= raw_regnums->fplast_regnum
+ && !FP_REGISTER_DOUBLE && MIPS_FPU_TYPE == MIPS_FPU_DOUBLE)
+ {
+ int cooked_offset0, cooked_offset1;
+
+ gdb_assert (cooked_size == 8
+ && cooked_regnums->fplast_regnum
+ - cooked_regnums->fp0_regnum + 1 == 16);
+
+ if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+ {
+ if (raw_size == 8)
+ raw_offset = 4;
+ else
+ raw_offset = 0;
+ cooked_offset0 = 4;
+ cooked_offset1 = 0;
+ }
+ else
+ {
+ raw_offset = 0;
+ cooked_offset0 = 0;
+ cooked_offset1 = 4;
+ }
+
+ if (raw_size > cooked_size)
+ {
+ /* Read entire contents of register that we're going to write
+ to so as not to perturb the excess bits. */
+ regcache_raw_read (regcache, raw_regno, raw_buf);
+ }
+ memcpy (raw_buf + raw_offset, (char *) buffer + cooked_offset0, 4);
+ regcache_raw_write (regcache, raw_regno, raw_buf);
+
+ if (raw_size > cooked_size)
+ {
+ /* Read entire contents of register that we're going to write
+ to so as not to perturb the excess bits. */
+ regcache_raw_read (regcache, raw_regno + 1, raw_buf);
+ }
+ memcpy (raw_buf + raw_offset, (char *) buffer + cooked_offset1, 4);
+ regcache_raw_write (regcache, raw_regno + 1, raw_buf);
+ }
+ else
+ {
+ if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+ raw_offset = raw_size - cooked_size;
+ else
+ raw_offset = 0;
+
+ gdb_assert (raw_offset >= 0);
+
+ if (raw_size > cooked_size)
+ {
+ /* Read entire contents of register that we're going to write
+ to so as not to perturb the excess bits. */
+ regcache_raw_read (regcache, raw_regno, raw_buf);
+ }
+
+ memcpy (raw_buf + raw_offset, buffer, cooked_size);
+ regcache_raw_write (regcache, raw_regno, raw_buf);
+ }
+}
+
/* Copy a 32-bit single-precision value from the current frame
into rare_buffer. */
@@ -3912,35 +4437,8 @@ mips_read_fp_register_single (int regno,
static void
mips_read_fp_register_double (int regno, char *rare_buffer)
{
- int raw_size = REGISTER_RAW_SIZE (regno);
-
- if (raw_size == 8 && !mips2_fp_compat ())
- {
- /* We have a 64-bit value for this register, and we should use
- all 64 bits. */
- if (!frame_register_read (deprecated_selected_frame, regno, rare_buffer))
- error ("can't read register %d (%s)", regno, REGISTER_NAME (regno));
- }
- else
- {
- if ((regno - FP0_REGNUM) & 1)
- internal_error (__FILE__, __LINE__,
- "mips_read_fp_register_double: bad access to "
- "odd-numbered FP register");
-
- /* mips_read_fp_register_single will find the correct 32 bits from
- each register. */
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
- {
- mips_read_fp_register_single (regno, rare_buffer + 4);
- mips_read_fp_register_single (regno + 1, rare_buffer);
- }
- else
- {
- mips_read_fp_register_single (regno, rare_buffer);
- mips_read_fp_register_single (regno + 1, rare_buffer + 4);
- }
- }
+ if (!frame_register_read (deprecated_selected_frame, regno, rare_buffer))
+ error ("can't read register %d (%s)", regno, REGISTER_NAME (regno));
}
static void
@@ -3949,33 +4447,43 @@ mips_print_fp_register (int regnum)
char *raw_buffer;
double doub, flt1, flt2; /* doubles extracted from raw hex data */
int inv1, inv2, namelen;
+ const char *regname;
+
+ raw_buffer = (char *) alloca (REGISTER_RAW_SIZE (regnum));
- raw_buffer = (char *) alloca (2 * REGISTER_RAW_SIZE (FP0_REGNUM));
+ regname = REGISTER_NAME (regnum);
- printf_filtered ("%s:", REGISTER_NAME (regnum));
- printf_filtered ("%*s", 4 - (int) strlen (REGISTER_NAME (regnum)), "");
+ /* Print the register name. */
+ printf_filtered ("%s:", regname);
+ printf_filtered ("%*s", 4 - (int) strlen (regname), "");
- if (REGISTER_RAW_SIZE (regnum) == 4 || mips2_fp_compat ())
+ if (mips2_fp_compat ())
{
- /* 4-byte registers: Print hex and floating. Also print even
- numbered registers as doubles. */
+ /* 4-byte registers:
+
+ For even numbered registers in a double precision fpu, print
+ the even and the next odd as 64-bit hex, print the single
+ precision float value, and print the even/odd combo as a double.
+
+ Otherwise, for single precision fpus, print the register both as
+ 32-bit hex and as a float. */
+
mips_read_fp_register_single (regnum, raw_buffer);
flt1 = unpack_double (mips_float_register_type (), raw_buffer, &inv1);
- print_scalar_formatted (raw_buffer, builtin_type_uint32, 'x', 'w',
- gdb_stdout);
-
- printf_filtered (" flt: ");
- if (inv1)
- printf_filtered (" <invalid float> ");
- else
- printf_filtered ("%-17.9g", flt1);
-
- if (regnum % 2 == 0)
+ if (MIPS_FPU_TYPE == MIPS_FPU_DOUBLE)
{
mips_read_fp_register_double (regnum, raw_buffer);
doub = unpack_double (mips_double_register_type (), raw_buffer,
&inv2);
+ print_scalar_formatted (raw_buffer, builtin_type_uint64, 'x', 'g',
+ gdb_stdout);
+
+ printf_filtered (" flt: ");
+ if (inv1)
+ printf_filtered (" <invalid float> ");
+ else
+ printf_filtered ("%-17.9g", flt1);
printf_filtered (" dbl: ");
if (inv2)
@@ -3983,6 +4491,18 @@ mips_print_fp_register (int regnum)
else
printf_filtered ("%-24.17g", doub);
}
+ else
+ {
+ print_scalar_formatted (raw_buffer, builtin_type_uint32, 'x', 'w',
+ gdb_stdout);
+
+ printf_filtered (" flt: ");
+ if (inv1)
+ printf_filtered (" <invalid float> ");
+ else
+ printf_filtered ("%-17.9g", flt1);
+
+ }
}
else
{
@@ -4017,7 +4537,7 @@ mips_print_register (int regnum, int all
char *raw_buffer = alloca (MAX_REGISTER_RAW_SIZE);
int offset;
- if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
+ if (mips_is_floating_point_register (regnum))
{
mips_print_fp_register (regnum);
return;
@@ -4047,7 +4567,7 @@ mips_print_register (int regnum, int all
offset = 0;
print_scalar_formatted (raw_buffer + offset,
- REGISTER_VIRTUAL_TYPE (regnum),
+ register_type (current_gdbarch, regnum),
'x', 0, gdb_stdout);
}
@@ -4057,6 +4577,15 @@ mips_print_register (int regnum, int all
static int
do_fp_register_row (int regnum)
{
+ const char * regname;
+
+ regname = REGISTER_NAME (regnum);
+ if (regname == NULL || *regname == '\0')
+ {
+ /* Don't print *anything* for the no-name registers. */
+ return regnum + 1;
+ }
+
printf_filtered (" ");
mips_print_fp_register (regnum);
printf_filtered ("\n");
@@ -4074,7 +4603,7 @@ do_gp_register_row (int regnum)
int ncols = (MIPS_REGSIZE == 8 ? 4 : 8); /* display cols per row */
int col, byte;
int start_regnum = regnum;
- int numregs = NUM_REGS;
+ int numregs = NUM_REGS + NUM_PSEUDO_REGS;
/* For GP registers, we print a separate row of names above the vals */
@@ -4083,8 +4612,8 @@ do_gp_register_row (int regnum)
{
if (*REGISTER_NAME (regnum) == '\0')
continue; /* unused register */
- if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
- break; /* end the row: reached FP register */
+ if (!mips_is_general_purpose_register (regnum))
+ continue; /* end the row: reached FP register */
printf_filtered (MIPS_REGSIZE == 8 ? "%17s" : "%9s",
REGISTER_NAME (regnum));
col++;
@@ -4098,8 +4627,8 @@ do_gp_register_row (int regnum)
{
if (*REGISTER_NAME (regnum) == '\0')
continue; /* unused register */
- if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
- break; /* end row: reached FP register */
+ if (!mips_is_general_purpose_register (regnum))
+ continue;
/* OK: get the data in raw format. */
if (!frame_register_read (deprecated_selected_frame, regnum, raw_buffer))
error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
@@ -4142,16 +4671,28 @@ mips_do_registers_info (int regnum, int
else
/* do all (or most) registers */
{
+ /* Do the general purpose registers. */
regnum = 0;
- while (regnum < NUM_REGS)
+ while (regnum < NUM_REGS + NUM_PSEUDO_REGS)
{
- if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
- if (fpregs) /* true for "INFO ALL-REGISTERS" command */
- regnum = do_fp_register_row (regnum); /* FP regs */
- else
- regnum += MIPS_NUMREGS; /* skip floating point regs */
- else
+ if (mips_is_general_purpose_register (regnum))
regnum = do_gp_register_row (regnum); /* GP (int) regs */
+ else
+ regnum++;
+ }
+
+ /* Do the floating point registers if requested, i.e, for
+ "info all-registers". */
+ if (fpregs) /* true for "INFO ALL-REGISTERS" command */
+ {
+ regnum = 0;
+ while (regnum < NUM_REGS + NUM_PSEUDO_REGS)
+ {
+ if (mips_is_floating_point_register (regnum))
+ regnum = do_fp_register_row (regnum); /* FP regs */
+ else
+ regnum++;
+ }
}
}
}
@@ -4432,6 +4973,7 @@ return_value_location (struct type *valt
struct return_value_word *lo)
{
int len = TYPE_LENGTH (valtype);
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
if (TYPE_CODE (valtype) == TYPE_CODE_FLT
&& ((MIPS_FPU_TYPE == MIPS_FPU_DOUBLE && (len == 4 || len == 8))
@@ -4444,11 +4986,11 @@ return_value_location (struct type *valt
lo->buf_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
hi->buf_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 0 : 4;
lo->reg_offset = ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
- && REGISTER_RAW_SIZE (FP0_REGNUM) == 8)
+ && REGISTER_RAW_SIZE (regnums->fp0_regnum) == 8)
? 4 : 0);
hi->reg_offset = lo->reg_offset;
- lo->reg = FP0_REGNUM + 0;
- hi->reg = FP0_REGNUM + 1;
+ lo->reg = regnums->fp0_regnum + 0;
+ hi->reg = regnums->fp0_regnum + 1;
lo->len = 4;
hi->len = 4;
}
@@ -4457,10 +4999,10 @@ return_value_location (struct type *valt
/* The floating point value fits in a single floating-point
register. */
lo->reg_offset = ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
- && REGISTER_RAW_SIZE (FP0_REGNUM) == 8
+ && REGISTER_RAW_SIZE (regnums->fp0_regnum) == 8
&& len == 4)
? 4 : 0);
- lo->reg = FP0_REGNUM;
+ lo->reg = regnums->fp0_regnum;
lo->len = len;
lo->buf_offset = 0;
hi->len = 0;
@@ -4622,6 +5164,8 @@ mips_o32_xfer_return_value (struct type
bfd_byte *in, const bfd_byte *out)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
if (TYPE_CODE (type) == TYPE_CODE_FLT
&& TYPE_LENGTH (type) == 4
&& tdep->mips_fpu_type != MIPS_FPU_NONE)
@@ -4630,7 +5174,7 @@ mips_o32_xfer_return_value (struct type
least significant part of FP0. */
if (mips_debug)
fprintf_unfiltered (gdb_stderr, "Return float in $fp0\n");
- mips_xfer_register (regcache, FP0_REGNUM, TYPE_LENGTH (type),
+ mips_xfer_register (regcache, regnums->fp0_regnum, TYPE_LENGTH (type),
TARGET_BYTE_ORDER, in, out, 0);
}
else if (TYPE_CODE (type) == TYPE_CODE_FLT
@@ -4645,15 +5189,15 @@ mips_o32_xfer_return_value (struct type
switch (TARGET_BYTE_ORDER)
{
case BFD_ENDIAN_LITTLE:
- mips_xfer_register (regcache, FP0_REGNUM + 0, 4,
+ mips_xfer_register (regcache, regnums->fp0_regnum + 0, 4,
TARGET_BYTE_ORDER, in, out, 0);
- mips_xfer_register (regcache, FP0_REGNUM + 1, 4,
+ mips_xfer_register (regcache, regnums->fp0_regnum + 1, 4,
TARGET_BYTE_ORDER, in, out, 4);
break;
case BFD_ENDIAN_BIG:
- mips_xfer_register (regcache, FP0_REGNUM + 1, 4,
+ mips_xfer_register (regcache, regnums->fp0_regnum + 1, 4,
TARGET_BYTE_ORDER, in, out, 0);
- mips_xfer_register (regcache, FP0_REGNUM + 0, 4,
+ mips_xfer_register (regcache, regnums->fp0_regnum + 0, 4,
TARGET_BYTE_ORDER, in, out, 4);
break;
default:
@@ -4680,7 +5224,7 @@ mips_o32_xfer_return_value (struct type
bfd_byte *reg = alloca (MAX_REGISTER_RAW_SIZE);
int regnum;
int field;
- for (field = 0, regnum = FP0_REGNUM;
+ for (field = 0, regnum = regnums->fp0_regnum;
field < TYPE_NFIELDS (type);
field++, regnum += 2)
{
@@ -4702,7 +5246,7 @@ mips_o32_xfer_return_value (struct type
mips_xfer_lower. */
int offset;
int regnum;
- for (offset = 0, regnum = V0_REGNUM;
+ for (offset = 0, regnum = regnums->v0_regnum;
offset < TYPE_LENGTH (type);
offset += REGISTER_RAW_SIZE (regnum), regnum++)
{
@@ -4724,7 +5268,7 @@ mips_o32_xfer_return_value (struct type
the ISA. mips_stack_argsize controls this. */
int offset;
int regnum;
- for (offset = 0, regnum = V0_REGNUM;
+ for (offset = 0, regnum = regnums->v0_regnum;
offset < TYPE_LENGTH (type);
offset += mips_stack_argsize (), regnum++)
{
@@ -4763,6 +5307,8 @@ mips_n32n64_xfer_return_value (struct ty
bfd_byte *in, const bfd_byte *out)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
if (TYPE_CODE (type) == TYPE_CODE_FLT
&& tdep->mips_fpu_type != MIPS_FPU_NONE)
{
@@ -4770,7 +5316,7 @@ mips_n32n64_xfer_return_value (struct ty
of FP0. */
if (mips_debug)
fprintf_unfiltered (gdb_stderr, "Return float in $fp0\n");
- mips_xfer_register (regcache, FP0_REGNUM, TYPE_LENGTH (type),
+ mips_xfer_register (regcache, regnums->fp0_regnum, TYPE_LENGTH (type),
TARGET_BYTE_ORDER, in, out, 0);
}
else if (TYPE_CODE (type) == TYPE_CODE_STRUCT
@@ -4792,7 +5338,7 @@ mips_n32n64_xfer_return_value (struct ty
bfd_byte *reg = alloca (MAX_REGISTER_RAW_SIZE);
int regnum;
int field;
- for (field = 0, regnum = FP0_REGNUM;
+ for (field = 0, regnum = regnums->fp0_regnum;
field < TYPE_NFIELDS (type);
field++, regnum += 2)
{
@@ -4812,7 +5358,7 @@ mips_n32n64_xfer_return_value (struct ty
mips_xfer_lower. */
int offset;
int regnum;
- for (offset = 0, regnum = V0_REGNUM;
+ for (offset = 0, regnum = regnums->v0_regnum;
offset < TYPE_LENGTH (type);
offset += REGISTER_RAW_SIZE (regnum), regnum++)
{
@@ -4832,7 +5378,7 @@ mips_n32n64_xfer_return_value (struct ty
justified. */
int offset;
int regnum;
- for (offset = 0, regnum = V0_REGNUM;
+ for (offset = 0, regnum = regnums->v0_regnum;
offset < TYPE_LENGTH (type);
offset += REGISTER_RAW_SIZE (regnum), regnum++)
{
@@ -4875,9 +5421,10 @@ mips_extract_struct_value_address (struc
/* FIXME: This will only work at random. The caller passes the
struct_return address in V0, but it is not preserved. It may
still be there, or this may be a random value. */
+ const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
LONGEST val;
- regcache_cooked_read_signed (regcache, V0_REGNUM, &val);
+ regcache_cooked_read_signed (regcache, regnums->v0_regnum, &val);
return val;
}
@@ -5020,7 +5567,7 @@ mips_set_processor_type (char *str)
if (strcasecmp (str, mips_processor_type_table[i].name) == 0)
{
mips_processor_type = str;
- mips_processor_reg_names = mips_processor_type_table[i].regnames;
+ mips_embed_reg_names = mips_processor_type_table[i].regnames;
return 1;
/* FIXME tweak fpu flag too */
}
@@ -5036,8 +5583,12 @@ char *
mips_read_processor_type (void)
{
CORE_ADDR prid;
+ const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
+
+ if (regnums->prid_regnum < 0)
+ return NULL;
- prid = read_register (PRID_REGNUM);
+ prid = read_register (regnums->prid_regnum);
if ((prid & ~0xf) == 0x700)
return savestring ("r3041", strlen ("r3041"));
@@ -5196,6 +5747,7 @@ mips_skip_stub (CORE_ADDR pc)
{
char *name;
CORE_ADDR start_addr;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
/* Find the starting address and name of the function containing the PC. */
if (find_pc_partial_function (pc, &name, &start_addr, NULL) == 0)
@@ -5205,7 +5757,7 @@ mips_skip_stub (CORE_ADDR pc)
target PC is in $31 ($ra). */
if (strcmp (name, "__mips16_ret_sf") == 0
|| strcmp (name, "__mips16_ret_df") == 0)
- return read_signed_register (RA_REGNUM);
+ return read_signed_register (regnums->ra_regnum);
if (strncmp (name, "__mips16_call_stub_", 19) == 0)
{
@@ -5426,7 +5978,9 @@ mips_get_saved_register (char *raw_buffe
static CORE_ADDR
mips_saved_pc_after_call (struct frame_info *frame)
{
- return read_signed_register (RA_REGNUM);
+ const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
+
+ return read_signed_register (regnums->ra_regnum);
}
@@ -5436,14 +5990,21 @@ mips_saved_pc_after_call (struct frame_i
static int
mips_stab_reg_to_regnum (int num)
{
+ const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
+
if (num >= 0 && num < 32)
return num;
else if (num >= 38 && num < 70)
- return num + FP0_REGNUM - 38;
+ {
+ if (regnums->fplast_regnum - regnums->fp0_regnum + 1 == 16)
+ return ((num - 38) / 2) + regnums->fp0_regnum;
+ else
+ return num - 38 + regnums->fp0_regnum;
+ }
else if (num == 70)
- return HI_REGNUM;
+ return regnums->hi_regnum;
else if (num == 71)
- return LO_REGNUM;
+ return regnums->lo_regnum;
else
{
/* This will hopefully (eventually) provoke a warning. Should
@@ -5458,14 +6019,21 @@ mips_stab_reg_to_regnum (int num)
static int
mips_dwarf_dwarf2_ecoff_reg_to_regnum (int num)
{
+ const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
+
if (num >= 0 && num < 32)
return num;
else if (num >= 32 && num < 64)
- return num + FP0_REGNUM - 32;
+ {
+ if (regnums->fplast_regnum - regnums->fp0_regnum + 1 == 16)
+ return ((num - 32) / 2) + regnums->fp0_regnum;
+ else
+ return num - 32 + regnums->fp0_regnum;
+ }
else if (num == 64)
- return HI_REGNUM;
+ return regnums->hi_regnum;
else if (num == 65)
- return LO_REGNUM;
+ return regnums->lo_regnum;
else
{
/* This will hopefully (eventually) provoke a warning. Should
@@ -5540,6 +6108,7 @@ mips_gdbarch_init (struct gdbarch_info i
struct gdbarch_tdep *tdep;
int elf_flags;
enum mips_abi mips_abi, found_abi, wanted_abi;
+ int first_pseudo_regnum, next_available_pseudo_regnum;
/* Reset the disassembly info, in case it was set to something
non-default. */
@@ -5692,7 +6261,6 @@ mips_gdbarch_init (struct gdbarch_info i
set_gdbarch_float_bit (gdbarch, 32);
set_gdbarch_double_bit (gdbarch, 64);
set_gdbarch_long_double_bit (gdbarch, 64);
- set_gdbarch_register_raw_size (gdbarch, mips_register_raw_size);
set_gdbarch_deprecated_max_register_raw_size (gdbarch, 8);
set_gdbarch_deprecated_max_register_virtual_size (gdbarch, 8);
tdep->found_abi = found_abi;
@@ -5702,9 +6270,54 @@ mips_gdbarch_init (struct gdbarch_info i
mips_elf_make_msymbol_special);
if (info.osabi == GDB_OSABI_IRIX)
- set_gdbarch_num_regs (gdbarch, 71);
+ {
+ set_gdbarch_num_regs (gdbarch, 71);
+ first_pseudo_regnum = 71;
+ next_available_pseudo_regnum = 71;
+
+ tdep->raw_regnums.fp0_regnum = 32;
+ tdep->raw_regnums.pc_regnum = 64;
+ tdep->raw_regnums.cause_regnum = 65;
+ tdep->raw_regnums.badvaddr_regnum = 66;
+ tdep->raw_regnums.hi_regnum = 67;
+ tdep->raw_regnums.lo_regnum = 68;
+ tdep->raw_regnums.fcrcs_regnum = 69;
+ tdep->raw_regnums.fcrir_regnum = 70;
+
+ tdep->raw_regnums.ps_regnum = -1;
+ tdep->raw_regnums.first_embed_regnum = -1;
+ tdep->raw_regnums.last_embed_regnum = -1;
+ tdep->raw_regnums.prid_regnum = -1;
+ }
else
- set_gdbarch_num_regs (gdbarch, 90);
+ {
+ set_gdbarch_num_regs (gdbarch, 90);
+ first_pseudo_regnum = 90;
+ next_available_pseudo_regnum = 90;
+
+ tdep->raw_regnums.fp0_regnum = 38;
+ tdep->raw_regnums.ps_regnum = 32;
+ tdep->raw_regnums.hi_regnum = 34;
+ tdep->raw_regnums.lo_regnum = 33;
+ tdep->raw_regnums.badvaddr_regnum = 35;
+ tdep->raw_regnums.cause_regnum = 36;
+ tdep->raw_regnums.pc_regnum = 37;
+ tdep->raw_regnums.fcrcs_regnum = 70;
+ tdep->raw_regnums.fcrir_regnum = 71;
+ tdep->raw_regnums.first_embed_regnum = 74;
+ tdep->raw_regnums.last_embed_regnum = 89;
+ tdep->raw_regnums.prid_regnum = 89;
+ }
+
+ tdep->raw_regnums.fplast_regnum = tdep->raw_regnums.fp0_regnum + 31;
+ tdep->raw_regnums.first_fp_arg_regnum = tdep->raw_regnums.fp0_regnum + 12;
+
+ tdep->raw_regnums.zero_regnum = 0;
+ tdep->raw_regnums.v0_regnum = 2;
+ tdep->raw_regnums.a0_regnum = 4;
+ tdep->raw_regnums.t9_regnum = 25;
+ tdep->raw_regnums.sp_regnum = 29;
+ tdep->raw_regnums.ra_regnum = 31;
switch (mips_abi)
{
@@ -5715,8 +6328,8 @@ mips_gdbarch_init (struct gdbarch_info i
tdep->mips_default_saved_regsize = 4;
tdep->mips_default_stack_argsize = 4;
tdep->mips_fp_register_double = 0;
- tdep->mips_last_arg_regnum = A0_REGNUM + 4 - 1;
- tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 4 - 1;
+ tdep->raw_regnums.last_arg_regnum = tdep->raw_regnums.a0_regnum + 4 - 1;
+ tdep->raw_regnums.last_fp_arg_regnum = tdep->raw_regnums.first_fp_arg_regnum + 4 - 1;
tdep->gdb_target_is_mips64 = 0;
tdep->default_mask_address_p = 0;
set_gdbarch_long_bit (gdbarch, 32);
@@ -5734,8 +6347,8 @@ mips_gdbarch_init (struct gdbarch_info i
tdep->mips_default_saved_regsize = 8;
tdep->mips_default_stack_argsize = 8;
tdep->mips_fp_register_double = 1;
- tdep->mips_last_arg_regnum = A0_REGNUM + 4 - 1;
- tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 4 - 1;
+ tdep->raw_regnums.last_arg_regnum = tdep->raw_regnums.a0_regnum + 4 - 1;
+ tdep->raw_regnums.last_fp_arg_regnum = tdep->raw_regnums.first_fp_arg_regnum + 4 - 1;
tdep->gdb_target_is_mips64 = 1;
tdep->default_mask_address_p = 0;
set_gdbarch_long_bit (gdbarch, 32);
@@ -5753,8 +6366,8 @@ mips_gdbarch_init (struct gdbarch_info i
tdep->mips_default_saved_regsize = 4;
tdep->mips_default_stack_argsize = 4;
tdep->mips_fp_register_double = 0;
- tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
- tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 8 - 1;
+ tdep->raw_regnums.last_arg_regnum = tdep->raw_regnums.a0_regnum + 8 - 1;
+ tdep->raw_regnums.last_fp_arg_regnum = tdep->raw_regnums.first_fp_arg_regnum + 8 - 1;
tdep->gdb_target_is_mips64 = 0;
tdep->default_mask_address_p = 0;
set_gdbarch_long_bit (gdbarch, 32);
@@ -5772,8 +6385,8 @@ mips_gdbarch_init (struct gdbarch_info i
tdep->mips_default_saved_regsize = 8;
tdep->mips_default_stack_argsize = 8;
tdep->mips_fp_register_double = 1;
- tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
- tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 8 - 1;
+ tdep->raw_regnums.last_arg_regnum = tdep->raw_regnums.a0_regnum + 8 - 1;
+ tdep->raw_regnums.last_fp_arg_regnum = tdep->raw_regnums.first_fp_arg_regnum + 8 - 1;
tdep->gdb_target_is_mips64 = 1;
tdep->default_mask_address_p = 0;
set_gdbarch_long_bit (gdbarch, 64);
@@ -5791,8 +6404,8 @@ mips_gdbarch_init (struct gdbarch_info i
tdep->mips_default_saved_regsize = 8;
tdep->mips_default_stack_argsize = 8;
tdep->mips_fp_register_double = 1;
- tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
- tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 8 - 1;
+ tdep->raw_regnums.last_arg_regnum = tdep->raw_regnums.a0_regnum + 8 - 1;
+ tdep->raw_regnums.last_fp_arg_regnum = tdep->raw_regnums.first_fp_arg_regnum + 8 - 1;
tdep->gdb_target_is_mips64 = 1;
tdep->default_mask_address_p = 0;
set_gdbarch_long_bit (gdbarch, 32);
@@ -5810,8 +6423,8 @@ mips_gdbarch_init (struct gdbarch_info i
tdep->mips_default_saved_regsize = 8;
tdep->mips_default_stack_argsize = 8;
tdep->mips_fp_register_double = 1;
- tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
- tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 8 - 1;
+ tdep->raw_regnums.last_arg_regnum = tdep->raw_regnums.a0_regnum + 8 - 1;
+ tdep->raw_regnums.last_fp_arg_regnum = tdep->raw_regnums.first_fp_arg_regnum + 8 - 1;
tdep->gdb_target_is_mips64 = 1;
tdep->default_mask_address_p = 0;
set_gdbarch_long_bit (gdbarch, 64);
@@ -5914,11 +6527,6 @@ mips_gdbarch_init (struct gdbarch_info i
set_gdbarch_deprecated_push_return_address (gdbarch, mips_push_return_address);
set_gdbarch_frame_align (gdbarch, mips_frame_align);
set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
- set_gdbarch_register_convertible (gdbarch, mips_register_convertible);
- set_gdbarch_register_convert_to_virtual (gdbarch,
- mips_register_convert_to_virtual);
- set_gdbarch_register_convert_to_raw (gdbarch,
- mips_register_convert_to_raw);
set_gdbarch_deprecated_frame_chain (gdbarch, mips_frame_chain);
set_gdbarch_frameless_function_invocation (gdbarch,
@@ -5942,9 +6550,7 @@ mips_gdbarch_init (struct gdbarch_info i
set_gdbarch_function_start_offset (gdbarch, 0);
- /* There are MIPS targets which do not yet use this since they still
- define REGISTER_VIRTUAL_TYPE. */
- set_gdbarch_register_virtual_type (gdbarch, mips_register_virtual_type);
+ set_gdbarch_register_type (gdbarch, mips_register_type);
set_gdbarch_register_virtual_size (gdbarch, generic_register_size);
set_gdbarch_deprecated_do_registers_info (gdbarch, mips_do_registers_info);
@@ -5962,6 +6568,72 @@ mips_gdbarch_init (struct gdbarch_info i
set_gdbarch_in_solib_call_trampoline (gdbarch, mips_in_call_stub);
set_gdbarch_in_solib_return_trampoline (gdbarch, mips_in_return_stub);
+ /* Add mips register groups. */
+ mips_add_reggroups (gdbarch);
+ set_gdbarch_register_reggroup_p (gdbarch, mips_register_reggroup_p);
+
+ /* For many registers, the cooked and raw register numbers are the same. */
+ tdep->cooked_regnums = tdep->raw_regnums;
+
+ /* For those that aren't the same, initialize the cooked register numbers. */
+ if (!tdep->mips_fp_register_double &&
+ tdep->mips_fpu_type == MIPS_FPU_DOUBLE)
+ {
+ /* There are 16 64-bit cooked floating point registers. */
+ tdep->cooked_regnums.fp0_regnum = next_available_pseudo_regnum;
+ next_available_pseudo_regnum += 16;
+ tdep->cooked_regnums.fplast_regnum = next_available_pseudo_regnum - 1;
+ }
+ else if (tdep->mips_fpu_type == MIPS_FPU_NONE)
+ {
+ /* There aren't any cooked floating point registers. */
+ tdep->cooked_regnums.fp0_regnum = -1;
+ tdep->cooked_regnums.fplast_regnum = -1;
+ }
+ else
+ {
+ /* There are 32 floating (cooked) point registers. */
+ tdep->cooked_regnums.fp0_regnum = next_available_pseudo_regnum;
+ next_available_pseudo_regnum += 32;
+ tdep->cooked_regnums.fplast_regnum = next_available_pseudo_regnum - 1;
+ }
+
+ if (tdep->raw_regnums.ps_regnum != -1)
+ tdep->cooked_regnums.ps_regnum = next_available_pseudo_regnum++;
+
+ if (tdep->raw_regnums.fcrcs_regnum != -1)
+ tdep->cooked_regnums.fcrcs_regnum = next_available_pseudo_regnum++;
+
+ if (tdep->raw_regnums.fcrir_regnum != -1)
+ tdep->cooked_regnums.fcrir_regnum = next_available_pseudo_regnum++;
+
+ if (tdep->raw_regnums.first_embed_regnum != -1)
+ {
+ tdep->cooked_regnums.first_embed_regnum = next_available_pseudo_regnum;
+ next_available_pseudo_regnum += (tdep->raw_regnums.last_embed_regnum
+ - tdep->raw_regnums.first_embed_regnum);
+ tdep->cooked_regnums.last_embed_regnum = next_available_pseudo_regnum++;
+
+ tdep->cooked_regnums.prid_regnum
+ = tdep->cooked_regnums.first_embed_regnum
+ + (tdep->raw_regnums.prid_regnum
+ - tdep->raw_regnums.first_embed_regnum);
+ }
+
+ /* Set up the pseudo reg count and the pseudo register reader/writer. */
+ if (next_available_pseudo_regnum > first_pseudo_regnum)
+ {
+ set_gdbarch_num_pseudo_regs (gdbarch, next_available_pseudo_regnum
+ - first_pseudo_regnum);
+ set_gdbarch_pseudo_register_read (gdbarch, mips_pseudo_register_read);
+ set_gdbarch_pseudo_register_write (gdbarch, mips_pseudo_register_write);
+ }
+
+ /* Set the sp and pc regnums to the cooked numbers. */
+
+ set_gdbarch_sp_regnum (gdbarch, tdep->cooked_regnums.sp_regnum);
+ set_gdbarch_pc_regnum (gdbarch, tdep->cooked_regnums.pc_regnum);
+
return gdbarch;
}
@@ -6010,6 +6682,56 @@ show_mips_abi (char *ignore_args, int fr
}
static void
+mips_dump_regnums (const char *prefix, const struct mips_regnums *regnums,
+ struct ui_file *file)
+{
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "fp0_regnum", regnums->fp0_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "fplast_regnum", regnums->fplast_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "last_arg_regnum", regnums->last_arg_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "first_fp_arg_regnum", regnums->first_fp_arg_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "last_fp_arg_regnum", regnums->last_fp_arg_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "zero_regnum", regnums->zero_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "v0_regnum", regnums->v0_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "a0_regnum", regnums->a0_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "t9_regnum", regnums->t9_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "sp_regnum", regnums->sp_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "ra_regnum", regnums->ra_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "ps_regnum", regnums->ps_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "hi_regnum", regnums->hi_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "lo_regnum", regnums->lo_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "badvaddr_regnum", regnums->badvaddr_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "cause_regnum", regnums->cause_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "pc_regnum", regnums->pc_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "fcrcs_regnum", regnums->fcrcs_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "fcrir_regnum", regnums->fcrir_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "first_embed_regnum", regnums->first_embed_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "last_embed_regnum", regnums->last_embed_regnum);
+ fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+ "prid_regnum", regnums->prid_regnum);
+}
+
+static void
mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
@@ -6055,6 +6777,10 @@ mips_dump_tdep (struct gdbarch *current_
"mips_dump_tdep: mips_mask_address_p() %d (default %d)\n",
mips_mask_address_p (),
tdep->default_mask_address_p);
+ mips_dump_regnums ("mips_dump_tdep: tdep->cooked_regnums.",
+ &tdep->cooked_regnums, file);
+ mips_dump_regnums ("mips_dump_tdep: tdep->raw_regnums.",
+ &tdep->raw_regnums, file);
}
fprintf_unfiltered (file,
"mips_dump_tdep: FP_REGISTER_DOUBLE = %d\n",
@@ -6070,10 +6796,6 @@ mips_dump_tdep (struct gdbarch *current_
"mips_dump_tdep: MIPS_EABI = %d\n",
MIPS_EABI);
fprintf_unfiltered (file,
- "mips_dump_tdep: MIPS_LAST_FP_ARG_REGNUM = %d (%d regs)\n",
- MIPS_LAST_FP_ARG_REGNUM,
- MIPS_LAST_FP_ARG_REGNUM - FPA0_REGNUM + 1);
- fprintf_unfiltered (file,
"mips_dump_tdep: MIPS_FPU_TYPE = %d (%s)\n",
MIPS_FPU_TYPE,
(MIPS_FPU_TYPE == MIPS_FPU_NONE ? "none"
@@ -6096,50 +6818,26 @@ mips_dump_tdep (struct gdbarch *current_
"mips_dump_tdep: MIPS_REGSIZE = %d\n",
MIPS_REGSIZE);
fprintf_unfiltered (file,
- "mips_dump_tdep: A0_REGNUM = %d\n",
- A0_REGNUM);
- fprintf_unfiltered (file,
"mips_dump_tdep: ADDR_BITS_REMOVE # %s\n",
XSTRING (ADDR_BITS_REMOVE(ADDR)));
fprintf_unfiltered (file,
"mips_dump_tdep: ATTACH_DETACH # %s\n",
XSTRING (ATTACH_DETACH));
fprintf_unfiltered (file,
- "mips_dump_tdep: BADVADDR_REGNUM = %d\n",
- BADVADDR_REGNUM);
- fprintf_unfiltered (file,
"mips_dump_tdep: BIG_BREAKPOINT = delete?\n");
fprintf_unfiltered (file,
- "mips_dump_tdep: CAUSE_REGNUM = %d\n",
- CAUSE_REGNUM);
- fprintf_unfiltered (file,
"mips_dump_tdep: DWARF_REG_TO_REGNUM # %s\n",
XSTRING (DWARF_REG_TO_REGNUM (REGNUM)));
fprintf_unfiltered (file,
"mips_dump_tdep: ECOFF_REG_TO_REGNUM # %s\n",
XSTRING (ECOFF_REG_TO_REGNUM (REGNUM)));
fprintf_unfiltered (file,
- "mips_dump_tdep: FCRCS_REGNUM = %d\n",
- FCRCS_REGNUM);
- fprintf_unfiltered (file,
- "mips_dump_tdep: FCRIR_REGNUM = %d\n",
- FCRIR_REGNUM);
- fprintf_unfiltered (file,
- "mips_dump_tdep: FIRST_EMBED_REGNUM = %d\n",
- FIRST_EMBED_REGNUM);
- fprintf_unfiltered (file,
- "mips_dump_tdep: FPA0_REGNUM = %d\n",
- FPA0_REGNUM);
- fprintf_unfiltered (file,
"mips_dump_tdep: GDB_TARGET_IS_MIPS64 = %d\n",
GDB_TARGET_IS_MIPS64);
fprintf_unfiltered (file,
"mips_dump_tdep: HAVE_NONSTEPPABLE_WATCHPOINT # %s\n",
XSTRING (HAVE_NONSTEPPABLE_WATCHPOINT));
fprintf_unfiltered (file,
- "mips_dump_tdep: HI_REGNUM = %d\n",
- HI_REGNUM);
- fprintf_unfiltered (file,
"mips_dump_tdep: IDT_BIG_BREAKPOINT = delete?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: IDT_LITTLE_BREAKPOINT = delete?\n");
@@ -6155,13 +6853,7 @@ mips_dump_tdep (struct gdbarch *current_
fprintf_unfiltered (file,
"mips_dump_tdep: IS_MIPS16_ADDR = FIXME!\n");
fprintf_unfiltered (file,
- "mips_dump_tdep: LAST_EMBED_REGNUM = %d\n",
- LAST_EMBED_REGNUM);
- fprintf_unfiltered (file,
"mips_dump_tdep: LITTLE_BREAKPOINT = delete?\n");
- fprintf_unfiltered (file,
- "mips_dump_tdep: LO_REGNUM = %d\n",
- LO_REGNUM);
#ifdef MACHINE_CPROC_FP_OFFSET
fprintf_unfiltered (file,
"mips_dump_tdep: MACHINE_CPROC_FP_OFFSET = %d\n",
@@ -6194,15 +6886,9 @@ mips_dump_tdep (struct gdbarch *current_
"mips_dump_tdep: MIPS_INSTLEN = %d\n",
MIPS_INSTLEN);
fprintf_unfiltered (file,
- "mips_dump_tdep: MIPS_LAST_ARG_REGNUM = %d (%d regs)\n",
- MIPS_LAST_ARG_REGNUM,
- MIPS_LAST_ARG_REGNUM - A0_REGNUM + 1);
- fprintf_unfiltered (file,
"mips_dump_tdep: MIPS_NUMREGS = %d\n",
MIPS_NUMREGS);
fprintf_unfiltered (file,
- "mips_dump_tdep: MIPS_REGISTER_NAMES = delete?\n");
- fprintf_unfiltered (file,
"mips_dump_tdep: MIPS_SAVED_REGSIZE = %d\n",
MIPS_SAVED_REGSIZE);
fprintf_unfiltered (file,
@@ -6214,9 +6900,6 @@ mips_dump_tdep (struct gdbarch *current_
fprintf_unfiltered (file,
"mips_dump_tdep: PMON_LITTLE_BREAKPOINT = delete?\n");
fprintf_unfiltered (file,
- "mips_dump_tdep: PRID_REGNUM = %d\n",
- PRID_REGNUM);
- fprintf_unfiltered (file,
"mips_dump_tdep: PRINT_EXTRA_FRAME_INFO # %s\n",
XSTRING (PRINT_EXTRA_FRAME_INFO (FRAME)));
fprintf_unfiltered (file,
@@ -6244,12 +6927,6 @@ mips_dump_tdep (struct gdbarch *current_
fprintf_unfiltered (file,
"mips_dump_tdep: PROC_SYMBOL = function?\n");
fprintf_unfiltered (file,
- "mips_dump_tdep: PS_REGNUM = %d\n",
- PS_REGNUM);
- fprintf_unfiltered (file,
- "mips_dump_tdep: RA_REGNUM = %d\n",
- RA_REGNUM);
- fprintf_unfiltered (file,
"mips_dump_tdep: REGISTER_CONVERT_FROM_TYPE # %s\n",
XSTRING (REGISTER_CONVERT_FROM_TYPE (REGNUM, VALTYPE, RAW_BUFFER)));
fprintf_unfiltered (file,
@@ -6323,9 +7000,6 @@ mips_dump_tdep (struct gdbarch *current_
"mips_dump_tdep: STOPPED_BY_WATCHPOINT # %s\n",
XSTRING (STOPPED_BY_WATCHPOINT (WS)));
fprintf_unfiltered (file,
- "mips_dump_tdep: T9_REGNUM = %d\n",
- T9_REGNUM);
- fprintf_unfiltered (file,
"mips_dump_tdep: TABULAR_REGISTER_OUTPUT = used?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: TARGET_CAN_USE_HARDWARE_WATCHPOINT # %s\n",
@@ -6360,14 +7034,6 @@ mips_dump_tdep (struct gdbarch *current_
#endif
fprintf_unfiltered (file,
"mips_dump_tdep: UNMAKE_MIPS16_ADDR = function?\n");
-#ifdef UNUSED_REGNUM
- fprintf_unfiltered (file,
- "mips_dump_tdep: UNUSED_REGNUM = %d\n",
- UNUSED_REGNUM);
-#endif
- fprintf_unfiltered (file,
- "mips_dump_tdep: V0_REGNUM = %d\n",
- V0_REGNUM);
fprintf_unfiltered (file,
"mips_dump_tdep: VM_MIN_ADDRESS = %ld\n",
(long) VM_MIN_ADDRESS);
@@ -6377,9 +7043,6 @@ mips_dump_tdep (struct gdbarch *current_
VX_NUM_REGS);
#endif
fprintf_unfiltered (file,
- "mips_dump_tdep: ZERO_REGNUM = %d\n",
- ZERO_REGNUM);
- fprintf_unfiltered (file,
"mips_dump_tdep: _PROC_MAGIC_ = %d\n",
_PROC_MAGIC_);
}
@@ -6526,4 +7189,15 @@ that would transfer 32 bits for some reg
&mips_debug, "Set mips debugging.\n\
When non-zero, mips specific debugging is enabled.", &setdebuglist),
&showdebuglist);
+
+ mips_type_float_double_register_big
+ = build_mips_type_float_double_register_big ();
+ mips_type_float_double_register_little
+ = build_mips_type_float_double_register_little ();
+ mips_type_float_single_register_big
+ = build_mips_type_float_single_register_big ();
+ mips_type_float_single_register_little
+ = build_mips_type_float_single_register_little ();
+
+ mips_init_reggroups ();
}
Index: mips-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/mips-tdep.h,v
retrieving revision 1.2
diff -u -p -r1.2 mips-tdep.h
--- mips-tdep.h 12 Apr 2003 17:41:25 -0000 1.2
+++ mips-tdep.h 9 May 2003 23:36:34 -0000
@@ -40,4 +40,40 @@ enum mips_abi
/* Return the MIPS ABI associated with GDBARCH. */
enum mips_abi mips_abi (struct gdbarch *gdbarch);
+struct mips_regnums
+ {
+ int fp0_regnum; /* First floating point register. */
+ int fplast_regnum; /* Last floating point register. */
+ int last_arg_regnum; /* Last general purpose register used for
+ passing arguments. (a0_regnum is the
+ first.) */
+ int first_fp_arg_regnum; /* First floating point register used for
+ passing floating point arguments. */
+ int last_fp_arg_regnum; /* Last floating point register used for
+ passing floating point arguments. */
+ int zero_regnum; /* The zero register; read-only, always 0. */
+ int v0_regnum; /* Function return value. */
+ int a0_regnum; /* First GPR used for passing arguments. */
+ int t9_regnum; /* Contains address of callee in PIC code. */
+ int sp_regnum; /* Stack pointer. */
+ int ra_regnum; /* Return address. */
+ int ps_regnum; /* Processor status. */
+ int hi_regnum; /* High portion of internal multiply/divide
+ register. */
+ int lo_regnum; /* Low portion of internal multiply/divide
+ register. */
+ int badvaddr_regnum; /* Address associated with
+ addressing exception. */
+ int cause_regnum; /* Describes last exception. */
+ int pc_regnum; /* Program counter. */
+ int fcrcs_regnum; /* FP control/status. */
+ int fcrir_regnum; /* FP implementation/revision. */
+ int first_embed_regnum; /* First CP0 register for embedded use. */
+ int last_embed_regnum; /* Last CP0 register for embedded use. */
+ int prid_regnum; /* Processor ID. */
+ };
+
+const struct mips_regnums *mips_raw_regnums (struct gdbarch *gdbarch);
+const struct mips_regnums *mips_cooked_regnums (struct gdbarch *gdbarch);
+
#endif /* MIPS_TDEP_H */
Index: mipsnbsd-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/mipsnbsd-nat.c,v
retrieving revision 1.1
diff -u -p -r1.1 mipsnbsd-nat.c
--- mipsnbsd-nat.c 21 May 2002 15:58:40 -0000 1.1
+++ mipsnbsd-nat.c 9 May 2003 23:36:34 -0000
@@ -22,6 +22,7 @@
#include "inferior.h"
#include "regcache.h"
+#include "mips-tdep.h"
#include "mipsnbsd-tdep.h"
#include <sys/types.h>
@@ -32,12 +33,16 @@
static int
getregs_supplies (int regno)
{
- return ((regno) >= ZERO_REGNUM && (regno) <= PC_REGNUM);
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
+ return (regno >= regnums->zero_regnum && regno <= regnums->pc_regnum);
}
void
fetch_inferior_registers (int regno)
{
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
if (regno == -1 || getregs_supplies (regno))
{
struct reg regs;
@@ -51,7 +56,7 @@ fetch_inferior_registers (int regno)
return;
}
- if (regno == -1 || regno >= FP0_REGNUM)
+ if (regno == -1 || regno >= regnums->fp0_regnum)
{
struct fpreg fpregs;
@@ -66,6 +71,8 @@ fetch_inferior_registers (int regno)
void
store_inferior_registers (int regno)
{
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
if (regno == -1 || getregs_supplies (regno))
{
struct reg regs;
@@ -84,7 +91,7 @@ store_inferior_registers (int regno)
return;
}
- if (regno == -1 || regno >= FP0_REGNUM)
+ if (regno == -1 || regno >= regnums->fp0_regnum)
{
struct fpreg fpregs;
Index: remote-mips.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-mips.c,v
retrieving revision 1.33
diff -u -p -r1.33 remote-mips.c
--- remote-mips.c 29 Apr 2003 01:49:47 -0000 1.33
+++ remote-mips.c 9 May 2003 23:36:35 -0000
@@ -36,6 +36,7 @@
#include "gdb_stat.h"
#include "regcache.h"
#include <ctype.h>
+#include "mips-tdep.h"
\f
/* Breakpoint types. Values 0, 1, and 2 must agree with the watch
@@ -1750,6 +1751,7 @@ mips_wait (ptid_t ptid, struct target_wa
char flags[20];
int nfields;
int i;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
interrupt_count = 0;
hit_watchpoint = 0;
@@ -1793,14 +1795,14 @@ mips_wait (ptid_t ptid, struct target_wa
{
char *buf = alloca (max_register_size (current_gdbarch));
- store_unsigned_integer (buf, REGISTER_RAW_SIZE (PC_REGNUM), rpc);
- supply_register (PC_REGNUM, buf);
+ store_unsigned_integer (buf, REGISTER_RAW_SIZE (regnums->pc_regnum), rpc);
+ supply_register (regnums->pc_regnum, buf);
- store_unsigned_integer (buf, REGISTER_RAW_SIZE (PC_REGNUM), rfp);
+ store_unsigned_integer (buf, REGISTER_RAW_SIZE (regnums->pc_regnum), rfp);
supply_register (30, buf); /* This register they are avoiding and so it is unnamed */
- store_unsigned_integer (buf, REGISTER_RAW_SIZE (SP_REGNUM), rsp);
- supply_register (SP_REGNUM, buf);
+ store_unsigned_integer (buf, REGISTER_RAW_SIZE (regnums->sp_regnum), rsp);
+ supply_register (regnums->sp_regnum, buf);
store_unsigned_integer (buf, REGISTER_RAW_SIZE (DEPRECATED_FP_REGNUM), 0);
supply_register (DEPRECATED_FP_REGNUM, buf);
@@ -1904,25 +1906,26 @@ mips_wait (ptid_t ptid, struct target_wa
static int
mips_map_regno (int regno)
{
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
if (regno < 32)
return regno;
- if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
- return regno - FP0_REGNUM + 32;
- switch (regno)
- {
- case PC_REGNUM:
- return REGNO_OFFSET + 0;
- case CAUSE_REGNUM:
- return REGNO_OFFSET + 1;
- case HI_REGNUM:
- return REGNO_OFFSET + 2;
- case LO_REGNUM:
- return REGNO_OFFSET + 3;
- case FCRCS_REGNUM:
- return REGNO_OFFSET + 4;
- case FCRIR_REGNUM:
- return REGNO_OFFSET + 5;
- default:
+ if (regno >= regnums->fp0_regnum && regno < regnums->fp0_regnum + 32)
+ return regno - regnums->fp0_regnum + 32;
+ else if (regno == regnums->pc_regnum)
+ return REGNO_OFFSET + 0;
+ else if (regno == regnums->cause_regnum)
+ return REGNO_OFFSET + 1;
+ else if (regno == regnums->hi_regnum)
+ return REGNO_OFFSET + 2;
+ else if (regno == regnums->lo_regnum)
+ return REGNO_OFFSET + 3;
+ else if (regno == regnums->fcrcs_regnum)
+ return REGNO_OFFSET + 4;
+ else if (regno == regnums->fcrir_regnum)
+ return REGNO_OFFSET + 5;
+ else
+ {
/* FIXME: Is there a way to get the status register? */
return 0;
}
@@ -1935,6 +1938,7 @@ mips_fetch_registers (int regno)
{
unsigned LONGEST val;
int err;
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
if (regno == -1)
{
@@ -1943,7 +1947,7 @@ mips_fetch_registers (int regno)
return;
}
- if (regno == DEPRECATED_FP_REGNUM || regno == ZERO_REGNUM)
+ if (regno == DEPRECATED_FP_REGNUM || regno == regnums->zero_regnum)
/* DEPRECATED_FP_REGNUM on the mips is a hack which is just
supposed to read zero (see also mips-nat.c). */
val = 0;
@@ -3426,6 +3430,8 @@ pmon_load_fast (char *file)
static void
mips_load (char *file, int from_tty)
{
+ const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
/* Get the board out of remote debugging mode. */
if (mips_exit_debug ())
error ("mips_load: Couldn't get into monitor mode.");
@@ -3443,7 +3449,7 @@ mips_load (char *file, int from_tty)
/* Work around problem where PMON monitor updates the PC after a load
to a different value than GDB thinks it has. The following ensures
that the write_pc() WILL update the PC value: */
- deprecated_register_valid[PC_REGNUM] = 0;
+ deprecated_register_valid[regnums->pc_regnum] = 0;
}
if (exec_bfd)
write_pc (bfd_get_start_address (exec_bfd));
Index: config/mips/nm-riscos.h
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/nm-riscos.h,v
retrieving revision 1.1.1.2
diff -u -p -r1.1.1.2 nm-riscos.h
--- config/mips/nm-riscos.h 7 Jul 1999 20:15:18 -0000 1.1.1.2
+++ config/mips/nm-riscos.h 9 May 2003 23:36:36 -0000
@@ -29,27 +29,27 @@
#define KERNEL_U_ADDR BSD43_UADDR
#define REGISTER_U_ADDR(addr, blockend, regno) \
- if (regno < FP0_REGNUM) \
+ if (regno < mips_raw_regnums (current_gdbarch)->fp0_regnum) \
addr = UPAGES*NBPG-EF_SIZE+4*((regno)+EF_AT-1); \
- else if (regno < PC_REGNUM) \
- addr = PCB_OFFSET(pcb_fpregs[0]) + 4*(regno-FP0_REGNUM); \
- else if (regno == PS_REGNUM) \
+ else if (regno < mips_raw_regnums (current_gdbarch)->pc_regnum) \
+ addr = PCB_OFFSET(pcb_fpregs[0]) + 4*(regno-mips_raw_regnums (current_gdbarch)->fp0_regnum); \
+ else if (regno == mips_raw_regnums (current_gdbarch)->ps_regnum) \
addr = UPAGES*NBPG-EF_SIZE+4*EF_SR; \
- else if (regno == BADVADDR_REGNUM) \
+ else if (regno == mips_raw_regnums (current_gdbarch)->badvaddr_regnum) \
addr = UPAGES*NBPG-EF_SIZE+4*EF_BADVADDR; \
- else if (regno == LO_REGNUM) \
+ else if (regno == mips_raw_regnums (current_gdbarch)->lo_regnum) \
addr = UPAGES*NBPG-EF_SIZE+4*EF_MDLO; \
- else if (regno == HI_REGNUM) \
+ else if (regno == mips_raw_regnums (current_gdbarch)->hi_regnum) \
addr = UPAGES*NBPG-EF_SIZE+4*EF_MDHI; \
- else if (regno == CAUSE_REGNUM) \
+ else if (regno == mips_raw_regnums (current_gdbarch)->cause_regnum) \
addr = UPAGES*NBPG-EF_SIZE+4*EF_CAUSE; \
- else if (regno == PC_REGNUM) \
+ else if (regno == mips_raw_regnums (current_gdbarch)->pc_regnum) \
addr = UPAGES*NBPG-EF_SIZE+4*EF_EPC; \
- else if (regno < FCRCS_REGNUM) \
- addr = PCB_OFFSET(pcb_fpregs[0]) + 4*(regno-FP0_REGNUM); \
- else if (regno == FCRCS_REGNUM) \
+ else if (regno < mips_raw_regnums (current_gdbarch)->fcrcs_regnum) \
+ addr = PCB_OFFSET(pcb_fpregs[0]) + 4*(regno-mips_raw_regnums (current_gdbarch)->fp0_regnum); \
+ else if (regno == mips_raw_regnums (current_gdbarch)->fcrcs_regnum) \
addr = PCB_OFFSET(pcb_fpc_csr); \
- else if (regno == FCRIR_REGNUM) \
+ else if (regno == mips_raw_regnums (current_gdbarch)->fcrir_regnum) \
addr = PCB_OFFSET(pcb_fpc_eir); \
else \
addr = 0;
Index: config/mips/tm-irix3.h
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/tm-irix3.h,v
retrieving revision 1.5
diff -u -p -r1.5 tm-irix3.h
--- config/mips/tm-irix3.h 19 Mar 2003 06:21:14 -0000 1.5
+++ config/mips/tm-irix3.h 9 May 2003 23:36:36 -0000
@@ -21,44 +21,6 @@
#include "mips/tm-bigmips.h"
-/* Redefine register numbers for SGI. */
-
-#undef MIPS_REGISTER_NAMES
-#undef FP0_REGNUM
-#undef PC_REGNUM
-#undef HI_REGNUM
-#undef LO_REGNUM
-#undef CAUSE_REGNUM
-#undef BADVADDR_REGNUM
-#undef FCRCS_REGNUM
-#undef FCRIR_REGNUM
-
-/* Initializer for an array of names for registers 32 and above.
- There should be NUM_REGS-32 strings in this initializer. */
-
-#define MIPS_REGISTER_NAMES \
- { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
- "pc", "cause", "bad", "hi", "lo", "fsr", "fir" \
- }
-
-/* Register numbers of various important registers.
- Note that some of these values are "real" register numbers,
- and correspond to the general registers of the machine,
- and some are "phony" register numbers which are too large
- to be actual register numbers as far as the user is concerned
- but do serve to get the desired values when passed to read_register. */
-
-#define FP0_REGNUM 32 /* Floating point register 0 (single float) */
-#define PC_REGNUM 64 /* Contains program counter */
-#define CAUSE_REGNUM 65 /* describes last exception */
-#define BADVADDR_REGNUM 66 /* bad vaddr for addressing exception */
-#define HI_REGNUM 67 /* Multiple/divide temp */
-#define LO_REGNUM 68 /* ... */
-#define FCRCS_REGNUM 69 /* FP control/status */
-#define FCRIR_REGNUM 70 /* FP implementation/revision */
/* Offsets for register values in _sigtramp frame.
sigcontext is immediately above the _sigtramp frame on Irix. */
Index: config/mips/tm-irix5.h
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/tm-irix5.h,v
retrieving revision 1.8
diff -u -p -r1.8 tm-irix5.h
--- config/mips/tm-irix5.h 20 Aug 2002 13:17:55 -0000 1.8
+++ config/mips/tm-irix5.h 9 May 2003 23:36:39 -0000
@@ -21,36 +21,6 @@
#include "mips/tm-irix3.h"
-/* FIXME: cagney/2000-04-04: Testing the _MIPS_SIM_NABI32 and
- _MIPS_SIM in a tm-*.h file is simply wrong! Those are
- host-dependant macros (provided by /usr/include) and stop any
- chance of the target being cross compiled */
-#if defined (_MIPS_SIM_NABI32) && _MIPS_SIM == _MIPS_SIM_NABI32
-/*
- * Irix 6 (n32 ABI) has 32-bit GP regs and 64-bit FP regs
- */
-
-#undef REGISTER_BYTES
-#define REGISTER_BYTES (MIPS_NUMREGS * 8 + (NUM_REGS - MIPS_NUMREGS) * MIPS_REGSIZE)
-
-#undef REGISTER_BYTE
-#define REGISTER_BYTE(N) \
- (((N) < FP0_REGNUM) ? (N) * MIPS_REGSIZE : \
- ((N) < FP0_REGNUM + 32) ? \
- FP0_REGNUM * MIPS_REGSIZE + \
- ((N) - FP0_REGNUM) * sizeof(double) : \
- 32 * sizeof(double) + ((N) - 32) * MIPS_REGSIZE)
-
-#undef REGISTER_VIRTUAL_TYPE
-#define REGISTER_VIRTUAL_TYPE(N) \
- (((N) >= FP0_REGNUM && (N) < FP0_REGNUM+32) ? builtin_type_double \
- : ((N) == 32 /*SR*/) ? builtin_type_uint32 \
- : ((N) >= 70 && (N) <= 89) ? builtin_type_uint32 \
- : builtin_type_int)
-
-#endif /* N32 */
-
-
/* The signal handler trampoline is called _sigtramp. */
#undef IN_SIGTRAMP
#define IN_SIGTRAMP(pc, name) ((name) && STREQ ("_sigtramp", name))
Index: config/mips/tm-irix6.h
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/tm-irix6.h,v
retrieving revision 1.10
diff -u -p -r1.10 tm-irix6.h
--- config/mips/tm-irix6.h 19 Mar 2003 06:21:14 -0000 1.10
+++ config/mips/tm-irix6.h 9 May 2003 23:36:39 -0000
@@ -24,55 +24,9 @@
/* Redefine register numbers for SGI. */
-#undef MIPS_REGISTER_NAMES
-#undef FP0_REGNUM
-#undef PC_REGNUM
-#undef HI_REGNUM
-#undef LO_REGNUM
-#undef CAUSE_REGNUM
-#undef BADVADDR_REGNUM
-#undef FCRCS_REGNUM
-#undef FCRIR_REGNUM
-
-/* Initializer for an array of names for registers 32 and above.
- There should be NUM_REGS-32 strings in this initializer. */
-
-#define MIPS_REGISTER_NAMES \
- { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
- "pc", "cause", "bad", "hi", "lo", "fsr", "fir" \
- }
-
-/* Register numbers of various important registers.
- Note that some of these values are "real" register numbers,
- and correspond to the general registers of the machine,
- and some are "phony" register numbers which are too large
- to be actual register numbers as far as the user is concerned
- but do serve to get the desired values when passed to read_register. */
-
-#define FP0_REGNUM 32 /* Floating point register 0 (single float) */
-#define PC_REGNUM 64 /* Contains program counter */
-#define CAUSE_REGNUM 65 /* describes last exception */
-#define BADVADDR_REGNUM 66 /* bad vaddr for addressing exception */
-#define HI_REGNUM 67 /* Multiple/divide temp */
-#define LO_REGNUM 68 /* ... */
-#define FCRCS_REGNUM 69 /* FP control/status */
-#define FCRIR_REGNUM 70 /* FP implementation/revision */
-
-
#undef REGISTER_BYTES
#define REGISTER_BYTES (MIPS_NUMREGS * 8 + (NUM_REGS - MIPS_NUMREGS) * MIPS_REGSIZE)
-#undef REGISTER_BYTE
-#define REGISTER_BYTE(N) \
- (((N) < FP0_REGNUM) ? (N) * MIPS_REGSIZE : \
- ((N) < FP0_REGNUM + 32) ? \
- FP0_REGNUM * MIPS_REGSIZE + \
- ((N) - FP0_REGNUM) * sizeof(double) : \
- 32 * sizeof(double) + ((N) - 32) * MIPS_REGSIZE)
-
/* The signal handler trampoline is called _sigtramp. */
#undef IN_SIGTRAMP
#define IN_SIGTRAMP(pc, name) ((name) && STREQ ("_sigtramp", name))
@@ -99,6 +53,3 @@
/* Select the disassembler */
#undef TM_PRINT_INSN_MACH
#define TM_PRINT_INSN_MACH bfd_mach_mips8000
-
-/* Undefine those methods which have been multiarched. */
-#undef REGISTER_VIRTUAL_TYPE
Index: config/mips/tm-mips.h
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/tm-mips.h,v
retrieving revision 1.48
diff -u -p -r1.48 tm-mips.h
--- config/mips/tm-mips.h 5 May 2003 17:56:56 -0000 1.48
+++ config/mips/tm-mips.h 9 May 2003 23:36:39 -0000
@@ -59,88 +59,10 @@ extern int mips_step_skips_delay (CORE_A
#define MIPS_REGSIZE 4
#endif
-/* Initializer for an array of names for registers 32 and above.
- There should be NUM_REGS-32 strings in this initializer. */
-
-#ifndef MIPS_REGISTER_NAMES
-#define MIPS_REGISTER_NAMES \
- { "sr", "lo", "hi", "bad", "cause","pc", \
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
- "fsr", "fir", ""/*"fp"*/, "", \
- "", "", "", "", "", "", "", "", \
- "", "", "", "", "", "", "", "", \
- }
-#endif
-
-/* Register numbers of various important registers.
- Note that some of these values are "real" register numbers,
- and correspond to the general registers of the machine,
- and some are "phony" register numbers which are too large
- to be actual register numbers as far as the user is concerned
- but do serve to get the desired values when passed to read_register. */
-
-#define ZERO_REGNUM 0 /* read-only register, always 0 */
-#define V0_REGNUM 2 /* Function integer return value */
-#define A0_REGNUM 4 /* Loc of first arg during a subr call */
-#define T9_REGNUM 25 /* Contains address of callee in PIC */
-#define SP_REGNUM 29 /* Contains address of top of stack */
-#define RA_REGNUM 31 /* Contains return address value */
-#define PS_REGNUM 32 /* Contains processor status */
-#define HI_REGNUM 34 /* Multiple/divide temp */
-#define LO_REGNUM 33 /* ... */
-#define BADVADDR_REGNUM 35 /* bad vaddr for addressing exception */
-#define CAUSE_REGNUM 36 /* describes last exception */
-#define PC_REGNUM 37 /* Contains program counter */
-#define FP0_REGNUM 38 /* Floating point register 0 (single float) */
-#define FPA0_REGNUM (FP0_REGNUM+12) /* First float argument register */
-#define FCRCS_REGNUM 70 /* FP control/status */
-#define FCRIR_REGNUM 71 /* FP implementation/revision */
-#define UNUSED_REGNUM 73 /* Never used, FIXME */
-#define FIRST_EMBED_REGNUM 74 /* First CP0 register for embedded use */
-#define PRID_REGNUM 89 /* Processor ID */
-#define LAST_EMBED_REGNUM 89 /* Last one */
-
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES (NUM_REGS*MIPS_REGSIZE)
-
-/* Index within `registers' of the first byte of the space for
- register N. */
-
-#define REGISTER_BYTE(N) ((N) * MIPS_REGSIZE)
-
-/* Return the GDB type object for the "standard" data type of data in
- register N. */
-
-#ifndef REGISTER_VIRTUAL_TYPE
-#define REGISTER_VIRTUAL_TYPE(N) \
- (((N) >= FP0_REGNUM && (N) < FP0_REGNUM+32) ? builtin_type_float \
- : ((N) == 32 /*SR*/) ? builtin_type_uint32 \
- : ((N) >= 70 && (N) <= 89) ? builtin_type_uint32 \
- : builtin_type_int)
-#endif
-
-/* All mips targets store doubles in a register pair with the least
- significant register in the lower numbered register.
- If the target is big endian, double register values need conversion
- between memory and register formats. */
-
-extern void mips_register_convert_to_type (int regnum,
- struct type *type,
- char *buffer);
-extern void mips_register_convert_from_type (int regnum,
- struct type *type,
- char *buffer);
-
-#define REGISTER_CONVERT_TO_TYPE(n, type, buffer) \
- mips_register_convert_to_type ((n), (type), (buffer))
-
-#define REGISTER_CONVERT_FROM_TYPE(n, type, buffer) \
- mips_register_convert_from_type ((n), (type), (buffer))
\f
/* Special symbol found in blocks associated with routines. We can hang
Index: config/mips/tm-mips64.h
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/tm-mips64.h,v
retrieving revision 1.5
diff -u -p -r1.5 tm-mips64.h
--- config/mips/tm-mips64.h 5 Jun 2002 19:18:25 -0000 1.5
+++ config/mips/tm-mips64.h 9 May 2003 23:36:39 -0000
@@ -22,13 +22,6 @@
/* Use eight byte registers. */
#define MIPS_REGSIZE 8
-/* define 8 byte register type */
-#define REGISTER_VIRTUAL_TYPE(N) \
- (((N) >= FP0_REGNUM && (N) < FP0_REGNUM+32) ? builtin_type_double \
- : ((N) == 32 /*SR*/) ? builtin_type_uint32 \
- : ((N) >= 70 && (N) <= 89) ? builtin_type_uint32 \
- : builtin_type_long_long)
-
/* Load double words in CALL_DUMMY. */
#define OP_LDFPR 065 /* ldc1 */
#define OP_LDGPR 067 /* ld */
Index: config/mips/tm-tx39.h
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/tm-tx39.h,v
retrieving revision 1.6
diff -u -p -r1.6 tm-tx39.h
--- config/mips/tm-tx39.h 19 Mar 2003 06:21:14 -0000 1.6
+++ config/mips/tm-tx39.h 9 May 2003 23:36:39 -0000
@@ -18,15 +18,3 @@
Boston, MA 02111-1307, USA. */
#include "mips/tm-bigmips.h"
-
-#undef MIPS_REGISTER_NAMES
-#define MIPS_REGISTER_NAMES \
- { "sr", "lo", "hi", "bad", "cause","pc", \
- "", "", "", "", "", "", "", "", \
- "", "", "", "", "", "", "", "", \
- "", "", "", "", "", "", "", "", \
- "", "", "", "", "", "", "", "", \
- "", "", "", "", \
- "", "", "", "", "", "", "", "", \
- "", "", "config", "cache", "debug", "depc", "epc", "" \
- }
Index: config/mips/tm-tx39l.h
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/tm-tx39l.h,v
retrieving revision 1.6
diff -u -p -r1.6 tm-tx39l.h
--- config/mips/tm-tx39l.h 19 Mar 2003 06:21:14 -0000 1.6
+++ config/mips/tm-tx39l.h 9 May 2003 23:36:39 -0000
@@ -18,15 +18,3 @@
Boston, MA 02111-1307, USA. */
#include "mips/tm-mips.h"
-
-#undef MIPS_REGISTER_NAMES
-#define MIPS_REGISTER_NAMES \
- { "sr", "lo", "hi", "bad", "cause","pc", \
- "", "", "", "", "", "", "", "", \
- "", "", "", "", "", "", "", "", \
- "", "", "", "", "", "", "", "", \
- "", "", "", "", "", "", "", "", \
- "", "", "", "", \
- "", "", "", "", "", "", "", "", \
- "", "", "config", "cache", "debug", "depc", "epc", "" \
- }
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-10 0:25 [WIP/RFC] MIPS registers overhaul Kevin Buettner
@ 2003-05-10 20:30 ` Andrew Cagney
2003-05-10 20:40 ` Daniel Jacobowitz
2003-05-14 22:00 ` Kevin Buettner
0 siblings, 2 replies; 46+ messages in thread
From: Andrew Cagney @ 2003-05-10 20:30 UTC (permalink / raw)
To: Kevin Buettner; +Cc: gdb-patches
> The patch below represents the results of trying to fix two problems
> related to floating point registers, stumbling at various points along
> the way, and realizing that I needed to fix even more...
>
> The two problems related to floating point registers that I started out
> trying to fix are the following:
>
> 1) On mips64, it's not possible to set a floating point register to
> a single precision value.
Hmm, ``oops''.
> 2) Again, on mips64, when running a program using the o32 ABI, floating
> point doubles were not being fetched from GDB's regcache correctly.
> For o32, floating point doubles are represented using register pairs,
> but, for mips64, each register is stored in a 64-bit container. When
> attempting to retrieve the value of a 64-bit double that should
> be retrieved by taking 32-bits from a pair, the single 64-bit container
> was being considered to be the value of the double.
For a long long time people were trying to solve this using the
convertible methods. It never really worked.
> Problem 1 was solved by introducing a union type for floating point
> registers. When attempting to display a value using ``print'', you'll
> see (with my patch) something like this:
>
> (gdb) p $f20
> $1 = {i = 4621199872640208077, f = -107374184, d = 8.9000000000000004}
>
> (If someone can think of more meaningful, but still terse field names for
> the above, please let me know.)
I'd try to be consistent with the other register unions, uint64 for
instance. As for the d/f, I don't know.
> Problem 2 was solved by introducing pseudo-registers for the floating point
> registers. Along the way (last Friday, I think), I ran into an assertion
> failure which caused me to make even more extensive changes to the MIPS code.
Ya! Finally!
> BTW, the raw floating point registers are still accessible. Doing
> "info registers raw" will display all of the raw registers. Or, if
> you know the names of the registers you want to display, you can do,
> e.g, "info registers raw_f20".
Hmm, is this necessary? Confusing? ``maint print
{raw-,cooked-,}registers'' are already available and provide access to
the underlying values.
``info registers'' should always display the target's underlying
register set. In the case of o32 running on a 64 bit ISA, the 64 bit
registers should be displayed.
> Which reminds me... I've introduced two sets of register numbers. I
> called these the "cooked" and "raw" regnums. In many cases, the
> cooked and raw numbers are the same. (They'll usually be the same
> when the raw and cooked types are the same.) In the cases where the
> numbers are different, the cooked number is a pseudo register number
> and the corresponding raw register is (usually) used to determine the
> value of cooked value. Raw registers numbers should be used by the
> lower layers of GDB which communicate with the target and need to
> populate GDB's regcache. The cooked registers *should* be used almost
> everywhere else. Except they aren't at the moment. In particular,
> most of mips-tdep.c wants to still operate on "raw" register data.
> (Anywhere you see a byte order check, that's a clue that raw register
> numbers should still be used.) So, in order to prevent this patch from
> becoming even larger than it already is, much of mips-tdep.c still
> uses raw register numbers. These should (probably) be cleaned up some
> day to use cooked numbers instead. (I need to check to make sure I
> have this as a comment in the code somewhere...)
>
> For the o32 case that I was originally trying to fix, we end up
> creating 16 64-bit cooked floating point registers of the union type
> mentioned above. The raw floating point registers (in pairs) are used
> to construct the cooked value. It's also possible to end up with no
> cooked floating point registers or 32-floating floating point
> registers, either 32- or 64-bit. (The values of FP_REGISTER_DOUBLE
> and MIPS_FPU_TYPE influence what exactly gets done.)
Ok.
> Index: mdebugread.c
The below isn't right.
RA_REGNUM is defined by both Alpha and MIPS. There are a number of long
standing problems with mdebug read vis:
tm-alpha.h:64:#define mips_extra_func_info alpha_extra_func_info
and hard-wiring the reference to RA_REGNUM just wouldn't work.
I'd leave RA_REGNUM as is (or put the definition in tm-mips*.h so that
it is clear that it still needs to be fixed).
> ===================================================================
> RCS file: /cvs/src/src/gdb/mdebugread.c,v
> retrieving revision 1.44
> diff -u -p -r1.44 mdebugread.c
> --- mdebugread.c 19 Mar 2003 19:45:49 -0000 1.44
> +++ mdebugread.c 9 May 2003 23:36:32 -0000
> @@ -55,6 +55,9 @@
> #include "gdb_assert.h"
> #include "block.h"
>
> +#include "mips-tdep.h"
> +#define RA_REGNUM (mips_cooked_regnums (current_gdbarch)->ra_regnum)
> +
> /* These are needed if the tm.h file does not contain the necessary
> mips specific definitions. */
>
> @@ -69,9 +72,6 @@ typedef struct mips_extra_func_info
> PDR pdr;
> }
> *mips_extra_func_info_t;
> -#ifndef RA_REGNUM
> -#define RA_REGNUM 0
> -#endif
> #endif
>
> #ifdef USG
> Index: mips-tdep.h
Should there be separate raw and cooked num structures?
> +struct mips_regnums
> + {
> + int fp0_regnum; /* First floating point register. */
> + int fplast_regnum; /* Last floating point register. */
> + int last_arg_regnum; /* Last general purpose register used for
> + passing arguments. (a0_regnum is the
> + first.) */
> + int first_fp_arg_regnum; /* First floating point register used for
> + passing floating point arguments. */
> + int last_fp_arg_regnum; /* Last floating point register used for
> + passing floating point arguments. */
> + int zero_regnum; /* The zero register; read-only, always 0. */
> + int v0_regnum; /* Function return value. */
> + int a0_regnum; /* First GPR used for passing arguments. */
> + int t9_regnum; /* Contains address of callee in PIC code. */
> + int sp_regnum; /* Stack pointer. */
> + int ra_regnum; /* Return address. */
> + int ps_regnum; /* Processor status. */
> + int hi_regnum; /* High portion of internal multiply/divide
> + register. */
> + int lo_regnum; /* Low portion of internal multiply/divide
> + register. */
> + int badvaddr_regnum; /* Address associated with
> + addressing exception. */
> + int cause_regnum; /* Describes last exception. */
> + int pc_regnum; /* Program counter. */
> + int fcrcs_regnum; /* FP control/status. */
> + int fcrir_regnum; /* FP implementation/revision. */
> + int first_embed_regnum; /* First CP0 register for embedded use. */
> + int last_embed_regnum; /* Last CP0 register for embedded use. */
> + int prid_regnum; /* Processor ID. */
> + };
> +
> +const struct mips_regnums *mips_raw_regnums (struct gdbarch *gdbarch);
> +const struct mips_regnums *mips_cooked_regnums (struct gdbarch *gdbarch);
or at least keep things like "last_arg_regnum" out this space (they only
belong in one of the two spaces). Having them appear in both makes it
too easy to do the wrong thing.
Can I suggest for this code:
> mips_linux_cannot_fetch_register (int regno)
> {
> + const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
use a consistent nameing schema that makes the register's space clear vis:
rawnums = mips_raw_regnums (...);
...
if (regno == rawnums->ps_regnum)
it should be possible to apply separate patches that:
- add mips_raw_regnums() and their initialization
- roll out the mechanical change
s/BADVADDR_REGNUM/rawnums->badvaddr_regnum/
How do you know that the raw register numbers were computed correctly?
--
-#define REGISTER_PTRACE_ADDR(regno) \
+register_ptrace_addr (int regno)
is obvious (and separate also).
--
Make certain you use "mips-tdep.h" and not <mips-tdep.h>.
--
Delete the lsi33k support as Stan noted, it likely never worked
(separate also).
--
This should greatly reduce the diff to just the change adding the
cooked<->raw map, and code using it.
Andrew
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-10 20:30 ` Andrew Cagney
@ 2003-05-10 20:40 ` Daniel Jacobowitz
2003-05-14 22:00 ` Kevin Buettner
1 sibling, 0 replies; 46+ messages in thread
From: Daniel Jacobowitz @ 2003-05-10 20:40 UTC (permalink / raw)
To: Andrew Cagney; +Cc: Kevin Buettner, gdb-patches
On Sat, May 10, 2003 at 04:29:37PM -0400, Andrew Cagney wrote:
> >Problem 1 was solved by introducing a union type for floating point
> >registers. When attempting to display a value using ``print'', you'll
> >see (with my patch) something like this:
> >
> > (gdb) p $f20
> > $1 = {i = 4621199872640208077, f = -107374184, d = 8.9000000000000004}
> >
> >(If someone can think of more meaningful, but still terse field names for
> >the above, please let me know.)
>
> I'd try to be consistent with the other register unions, uint64 for
> instance. As for the d/f, I don't know.
How about u64, flt, and dbl?
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-10 20:30 ` Andrew Cagney
2003-05-10 20:40 ` Daniel Jacobowitz
@ 2003-05-14 22:00 ` Kevin Buettner
[not found] ` <mailpost.1052949911.28802@news-sj1-1>
` (2 more replies)
1 sibling, 3 replies; 46+ messages in thread
From: Kevin Buettner @ 2003-05-14 22:00 UTC (permalink / raw)
To: Andrew Cagney; +Cc: gdb-patches
On May 10, 4:29pm, Andrew Cagney wrote:
> > Problem 1 was solved by introducing a union type for floating point
> > registers. When attempting to display a value using ``print'', you'll
> > see (with my patch) something like this:
> >
> > (gdb) p $f20
> > $1 = {i = 4621199872640208077, f = -107374184, d = 8.9000000000000004}
> >
> > (If someone can think of more meaningful, but still terse field names for
> > the above, please let me know.)
>
> I'd try to be consistent with the other register unions, uint64 for
> instance. As for the d/f, I don't know.
I like Daniel's suggestion for the names: u64, flt, and dbl. (flt and dbl
match the prefixes used by "info float".)
> > BTW, the raw floating point registers are still accessible. Doing
> > "info registers raw" will display all of the raw registers. Or, if
> > you know the names of the registers you want to display, you can do,
> > e.g, "info registers raw_f20".
>
> Hmm, is this necessary? Confusing? ``maint print
> {raw-,cooked-,}registers'' are already available and provide access to
> the underlying values.
Maybe we need to name the prefix something different than "raw_"?
Whatever we call them, I think it's still useful to have names
associated with them. E.g, you can do any of the following:
print $raw_f20
print/x ($raw_f20 >> 32)
set $raw_f20=0xbadbeef
Most of the time, you'll just want to deal with $f20 though. If you
suspect that something funny is going on with GDB's raw->cooked
translation, being able to more directly manipulate the raw values
could prove to be useful.
Also, due to the fact that most of the code in mips-tdep.c still uses
raw register numbers, you'll see the raw names showing up in "info
frame". E.g.:
(gdb) info frame
...
Saved registers:
gp at 0x7fff7d04, s8 at 0x7fff7d08, ra at 0x7fff7d0c, pc at 0x7fff7d0c,
raw_f20 at 0x7fff7d10, raw_f21 at 0x7fff7d14, f20 at 0x7fff7d10
^^^^^^
In the fullness of time, i.e, when the MIPS code is finally converted
to use cooked registers everywhere that it *should*, the above
references to the "raw" register names can probably go away.
> ``info registers'' should always display the target's underlying
> register set. In the case of o32 running on a 64 bit ISA, the 64 bit
> registers should be displayed.
Well, in this case the underlying register set really is only 32-bits
wide. Volume 1 of the MIPS64 Architecture (revision 1.00, dated
August 29, 2002) says:
For compatibility with MIPS32 processors, the FR bit in the CP0
Status register is used by a MIPS64 processor to configure the FPU
in a mode in which the FPRs are treated as 32 32-bit registers,
each of which is capable of storing only 32-bit data types. In
this mode, the double-precision floating point (type D) data type
is stored in even-odd pairs of FPRs, and the long-integer (type L)
and paired single (type PS) data types are not supported.
Figure 2-8 in this manual shows that bits 32-63 (i.e, the high 32 bits)
are "UNPREDICTABLE" in this mode.
We still *could* show these extra bits, but displaying the register in
this way would, most of the time, be next to useless. If the GDB user
really wants to see what the higher order bits are, then the raw_fN
names are useful.
[...]
> > Index: mdebugread.c
>
> The below isn't right.
>
> RA_REGNUM is defined by both Alpha and MIPS. There are a number of long
> standing problems with mdebug read vis:
> tm-alpha.h:64:#define mips_extra_func_info alpha_extra_func_info
> and hard-wiring the reference to RA_REGNUM just wouldn't work.
>
> I'd leave RA_REGNUM as is (or put the definition in tm-mips*.h so that
> it is clear that it still needs to be fixed).
I'll put RA_REGNUM back into mips-tdep.h along with a comment which
indicates that it should only used by mdebugread.c.
> > Index: mips-tdep.h
>
> Should there be separate raw and cooked num structures?
>
> > +struct mips_regnums
> > + {
> > + int fp0_regnum; /* First floating point register. */
> > + int fplast_regnum; /* Last floating point register. */
> > + int last_arg_regnum; /* Last general purpose register used for
> > + passing arguments. (a0_regnum is the
> > + first.) */
> > + int first_fp_arg_regnum; /* First floating point register used for
> > + passing floating point arguments. */
> > + int last_fp_arg_regnum; /* Last floating point register used for
> > + passing floating point arguments. */
> > + int zero_regnum; /* The zero register; read-only, always 0. */
> > + int v0_regnum; /* Function return value. */
> > + int a0_regnum; /* First GPR used for passing arguments. */
> > + int t9_regnum; /* Contains address of callee in PIC code. */
> > + int sp_regnum; /* Stack pointer. */
> > + int ra_regnum; /* Return address. */
> > + int ps_regnum; /* Processor status. */
> > + int hi_regnum; /* High portion of internal multiply/divide
> > + register. */
> > + int lo_regnum; /* Low portion of internal multiply/divide
> > + register. */
> > + int badvaddr_regnum; /* Address associated with
> > + addressing exception. */
> > + int cause_regnum; /* Describes last exception. */
> > + int pc_regnum; /* Program counter. */
> > + int fcrcs_regnum; /* FP control/status. */
> > + int fcrir_regnum; /* FP implementation/revision. */
> > + int first_embed_regnum; /* First CP0 register for embedded use. */
> > + int last_embed_regnum; /* Last CP0 register for embedded use. */
> > + int prid_regnum; /* Processor ID. */
> > + };
> > +
> > +const struct mips_regnums *mips_raw_regnums (struct gdbarch *gdbarch);
> > +const struct mips_regnums *mips_cooked_regnums (struct gdbarch *gdbarch);
>
> or at least keep things like "last_arg_regnum" out this space (they only
> belong in one of the two spaces). Having them appear in both makes it
> too easy to do the wrong thing.
Actually, I think it's useful for the layout raw and cooked regnum
structs to be identical. When initializing the cooked regnum struct,
we can do so via a single assignment:
/* For many registers, the cooked and raw register numbers are the same. */
tdep->cooked_regnums = tdep->raw_regnums;
/* Cooked regnum initializations that differ follow... */
The fact that the structs were identical made it easy and elegant to
define the reg_name() function which is used twice by mips_register_name(),
once for cooked register numbers, and a second time (assuming no suitable
cooked name was found) for the raw numbers. If the layout of the cooked
and raw structs were different, I'd need two separate functions with nearly
identical functionality. Ditto for mips_dump_regnums().
I think that you definitely want "last_arg_regnum" and
"last_fp_arg_regnum" to appear in both structs. At the moment, the
various MIPS *_push_argument() code uses the register names from the
raw regnums struct. I think it may be desirable at some point to make
this code use cooked regnums instead. (It will hopefully simplify a
bunch of code that worries about shifting values to the correct
position within a register.) For the floating point registers, where
the cooked and raw numbers are actually different, we would like
"first_fp_arg_regnum" and "last_fp_arg_regnum" to actually refer to
numbers within this space.
I think it's likely that when/if this conversion occurs, it'll be done
on an incremental basis. We want separate cooked/raw numbers so that
it can be done incrementally.
Also, putting these values in the regnum struct makes it clear exactly
which set they belong to.
> Can I suggest for this code:
>
> > mips_linux_cannot_fetch_register (int regno)
> > {
> > + const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
>
> use a consistent nameing schema that makes the register's space clear vis:
>
> rawnums = mips_raw_regnums (...);
> ...
> if (regno == rawnums->ps_regnum)
I'll adopt the following naming scheme:
rawnums - for code which uses and should continue to use raw numbers
cookednums - for code which uses and should continue to use cooked
numbers
regnums - for one of two cases, either code that's currently using
raw numbers that should be converted to be cooked, or
for code which I'm unsure of. (Either case, these'll
be raw numbers. When someone converts the code or decides
that the "raw" usage is correct, the name should be
changed.)
For the last category, I'm open to suggestions for some other name.
> it should be possible to apply separate patches that:
>
> - add mips_raw_regnums() and their initialization
> - roll out the mechanical change
> s/BADVADDR_REGNUM/rawnums->badvaddr_regnum/
Okay.
> How do you know that the raw register numbers were computed correctly?
I just used the same values as the macros used to use. The user can see
what they are via "maint print architecture".
(Maybe I don't understand your question.)
> -#define REGISTER_PTRACE_ADDR(regno) \
> +register_ptrace_addr (int regno)
>
> is obvious (and separate also).
Okay.
> Make certain you use "mips-tdep.h" and not <mips-tdep.h>.
Right. There was only one place that this happened. Not sure why.
It's been fixed in my sources.
> Delete the lsi33k support as Stan noted, it likely never worked
> (separate also).
I don't think that this is exactly what Stan noted, but okay.
> This should greatly reduce the diff to just the change adding the
> cooked<->raw map, and code using it.
Okay.
Kevin
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
[not found] ` <mailpost.1052949911.28802@news-sj1-1>
@ 2003-05-14 23:35 ` cgd
2003-05-15 0:07 ` Kevin Buettner
0 siblings, 1 reply; 46+ messages in thread
From: cgd @ 2003-05-14 23:35 UTC (permalink / raw)
To: kevinb; +Cc: Andrew Cagney, gdb-patches
At Wed, 14 May 2003 22:05:11 +0000 (UTC), "Kevin Buettner" wrote:
> > ``info registers'' should always display the target's underlying
> > register set. In the case of o32 running on a 64 bit ISA, the 64 bit
> > registers should be displayed.
>
> Well, in this case the underlying register set really is only 32-bits
> wide. Volume 1 of the MIPS64 Architecture (revision 1.00, dated
> August 29, 2002) says:
>
> For compatibility with MIPS32 processors, the FR bit in the CP0
> Status register is used by a MIPS64 processor to configure the FPU
> in a mode in which the FPRs are treated as 32 32-bit registers,
> each of which is capable of storing only 32-bit data types. In
> this mode, the double-precision floating point (type D) data type
> is stored in even-odd pairs of FPRs, and the long-integer (type L)
> and paired single (type PS) data types are not supported.
>
> Figure 2-8 in this manual shows that bits 32-63 (i.e, the high 32 bits)
> are "UNPREDICTABLE" in this mode.
Indeed.
> We still *could* show these extra bits, but displaying the register in
> this way would, most of the time, be next to useless. If the GDB user
> really wants to see what the higher order bits are, then the raw_fN
> names are useful.
One possible thing to do is display the upper 32 bits *if* you know
that Status:FR is set to 1. The Status:FR value is really the thing
that determines how the bits are interpreted.
Now, if o32, Status:FR *should* be 0.
However, I don't know if for old binaries being debugged o64 will be
detected properly (or, heck, even for new binaries 8-), and I also
know people who've done Really Special Things with o32 and soft float
and using library calls for all FP and using 64-bit floating point.
8-)
In other words, the real arbiter of the unpredictability of those bits
is Status:FR, so you should probably display them consistently with
what it says (if you have Status... I forget 8-).
I don't know enough about the remote protocol to know what one would
expect from a 64-bit debug agent debugging a 32-bit program (on a
64-bit target). But i could imagine it could become ugly very
quickly... 8-)
cgd
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-14 23:35 ` cgd
@ 2003-05-15 0:07 ` Kevin Buettner
2003-05-15 0:15 ` Daniel Jacobowitz
0 siblings, 1 reply; 46+ messages in thread
From: Kevin Buettner @ 2003-05-15 0:07 UTC (permalink / raw)
To: cgd, kevinb; +Cc: Andrew Cagney, gdb-patches
On May 14, 4:34pm, cgd@broadcom.com wrote:
> In other words, the real arbiter of the unpredictability of those bits
> is Status:FR, so you should probably display them consistently with
> what it says (if you have Status... I forget 8-).
I see the following in mips2_fp_compat():
#if 0
/* FIXME drow 2002-03-10: This is disabled until we can do it consistently,
in all the places we deal with FP registers. PR gdb/413. */
/* Otherwise check the FR bit in the status register - it controls
the FP compatiblity mode. If it is clear we are in compatibility
mode. */
if ((read_register (PS_REGNUM) & ST0_FR) == 0)
return 1;
#endif
I don't know the details, but it appears that there may be problems
with consistently being able to fetch the status register. (Maybe
it's not available on all MIPS targets that GDB supports?)
Anyone know?
Kevin
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-15 0:07 ` Kevin Buettner
@ 2003-05-15 0:15 ` Daniel Jacobowitz
0 siblings, 0 replies; 46+ messages in thread
From: Daniel Jacobowitz @ 2003-05-15 0:15 UTC (permalink / raw)
To: Kevin Buettner; +Cc: cgd, Andrew Cagney, gdb-patches
On Wed, May 14, 2003 at 05:07:16PM -0700, Kevin Buettner wrote:
> On May 14, 4:34pm, cgd@broadcom.com wrote:
>
> > In other words, the real arbiter of the unpredictability of those bits
> > is Status:FR, so you should probably display them consistently with
> > what it says (if you have Status... I forget 8-).
>
> I see the following in mips2_fp_compat():
>
> #if 0
> /* FIXME drow 2002-03-10: This is disabled until we can do it consistently,
> in all the places we deal with FP registers. PR gdb/413. */
> /* Otherwise check the FR bit in the status register - it controls
> the FP compatiblity mode. If it is clear we are in compatibility
> mode. */
> if ((read_register (PS_REGNUM) & ST0_FR) == 0)
> return 1;
> #endif
>
> I don't know the details, but it appears that there may be problems
> with consistently being able to fetch the status register. (Maybe
> it's not available on all MIPS targets that GDB supports?)
>
> Anyone know?
Hmm, I vaguely remember writing that. I don't think that's what I
meant by consistent - I just meant that we needed to use that function
everywhere appropriate. I believe Status is always available, so we
could use it to choose which FP registers are exposed.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-14 22:00 ` Kevin Buettner
[not found] ` <mailpost.1052949911.28802@news-sj1-1>
@ 2003-05-15 22:01 ` Kevin Buettner
2003-05-16 3:24 ` Andrew Cagney
2003-05-16 4:00 ` Andrew Cagney
2 siblings, 1 reply; 46+ messages in thread
From: Kevin Buettner @ 2003-05-15 22:01 UTC (permalink / raw)
To: Andrew Cagney; +Cc: gdb-patches
On May 14, 3:00pm, Kevin Buettner wrote:
> I'll adopt the following naming scheme:
>
> rawnums - for code which uses and should continue to use raw numbers
> cookednums - for code which uses and should continue to use cooked
> numbers
> regnums - for one of two cases, either code that's currently using
> raw numbers that should be converted to be cooked, or
> for code which I'm unsure of. (Either case, these'll
> be raw numbers. When someone converts the code or decides
> that the "raw" usage is correct, the name should be
> changed.)
>
> For the last category, I'm open to suggestions for some other name.
I've decided I don't like the name "regnums" that well for the last
category. I've settled on the name "rawnums_c" instead. The "_c"
suffix indicates that they *should* be cooked. (Yes, it's terse, but I
fear that anything longer will make the code unwieldy.) I'll also put
in a comment at each ``rawnums_c'' initialization indicating that the
code needs to be converted at some point to use cooked register
numbers. E.g.:
/* This function needs to be converted to use cooked register numbers. */
const struct mips_regnums *rawnums_c = mips_raw_regnums (gdbarch);
Kevin
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-15 22:01 ` Kevin Buettner
@ 2003-05-16 3:24 ` Andrew Cagney
0 siblings, 0 replies; 46+ messages in thread
From: Andrew Cagney @ 2003-05-16 3:24 UTC (permalink / raw)
To: Kevin Buettner; +Cc: gdb-patches
> On May 14, 3:00pm, Kevin Buettner wrote:
>
>
>> I'll adopt the following naming scheme:
>>
>> rawnums - for code which uses and should continue to use raw numbers
>> cookednums - for code which uses and should continue to use cooked
>> numbers
>> regnums - for one of two cases, either code that's currently using
>> raw numbers that should be converted to be cooked, or
>> for code which I'm unsure of. (Either case, these'll
>> be raw numbers. When someone converts the code or decides
>> that the "raw" usage is correct, the name should be
>> changed.)
>>
>> For the last category, I'm open to suggestions for some other name.
>
>
> I've decided I don't like the name "regnums" that well for the last
> category. I've settled on the name "rawnums_c" instead. The "_c"
> suffix indicates that they *should* be cooked. (Yes, it's terse, but I
> fear that anything longer will make the code unwieldy.) I'll also put
> in a comment at each ``rawnums_c'' initialization indicating that the
> code needs to be converted at some point to use cooked register
> numbers. E.g.:
>
> /* This function needs to be converted to use cooked register numbers. */
> const struct mips_regnums *rawnums_c = mips_raw_regnums (gdbarch);
I think this is "_c" convention is getting overly complicated. Just use
"rawnums" and "cookednums" and then leave the rest to comments.
Andrew
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-14 22:00 ` Kevin Buettner
[not found] ` <mailpost.1052949911.28802@news-sj1-1>
2003-05-15 22:01 ` Kevin Buettner
@ 2003-05-16 4:00 ` Andrew Cagney
2003-05-16 17:20 ` Kevin Buettner
[not found] ` <mailpost.1053057614.17325@news-sj1-1>
2 siblings, 2 replies; 46+ messages in thread
From: Andrew Cagney @ 2003-05-16 4:00 UTC (permalink / raw)
To: Kevin Buettner; +Cc: gdb-patches
> On May 10, 4:29pm, Andrew Cagney wrote:
>
>
>> > Problem 1 was solved by introducing a union type for floating point
>> > registers. When attempting to display a value using ``print'', you'll
>> > see (with my patch) something like this:
>> >
>> > (gdb) p $f20
>> > $1 = {i = 4621199872640208077, f = -107374184, d = 8.9000000000000004}
>> >
>> > (If someone can think of more meaningful, but still terse field names for
>> > the above, please let me know.)
>
>>
>> I'd try to be consistent with the other register unions, uint64 for
>> instance. As for the d/f, I don't know.
>
>
> I like Daniel's suggestion for the names: u64, flt, and dbl. (flt and dbl
> match the prefixes used by "info float".)
"flt" and "dbl" look ok, an alternative would be ieee754_{32,64} - ulgh.
"uint64", unlike "u64" is consistent with the existing convention.
>> > BTW, the raw floating point registers are still accessible. Doing
>> > "info registers raw" will display all of the raw registers. Or, if
>> > you know the names of the registers you want to display, you can do,
>> > e.g, "info registers raw_f20".
>
>>
>> Hmm, is this necessary? Confusing? ``maint print
>> {raw-,cooked-,}registers'' are already available and provide access to
>> the underlying values.
>
>
> Maybe we need to name the prefix something different than "raw_"?
>
> Whatever we call them, I think it's still useful to have names
> associated with them. E.g, you can do any of the following:
>
> print $raw_f20
> print/x ($raw_f20 >> 32)
> set $raw_f20=0xbadbeef
But how often will that actually happen?
I think a user debugging o32 on ISA64 still should expect to be
manipulating the full 64 bit register. Only on ISA32 should the
registers be restricted to their 32 bit values.
Even if the upper 32 bits of the FP registers are unpredictable, I think
they should still be displayed.
>> Should there be separate raw and cooked num structures?
>>
>
>> > +struct mips_regnums
>> > + {
>> > + int fp0_regnum; /* First floating point register. */
>> > + int fplast_regnum; /* Last floating point register. */
>> > + int last_arg_regnum; /* Last general purpose register used for
>> > + passing arguments. (a0_regnum is the
>> > + first.) */
>> > + int first_fp_arg_regnum; /* First floating point register used for
>> > + passing floating point arguments. */
>> > + int last_fp_arg_regnum; /* Last floating point register used for
>> > + passing floating point arguments. */
>> > + int zero_regnum; /* The zero register; read-only, always 0. */
>> > + int v0_regnum; /* Function return value. */
>> > + int a0_regnum; /* First GPR used for passing arguments. */
>> > + int t9_regnum; /* Contains address of callee in PIC code. */
>> > + int sp_regnum; /* Stack pointer. */
>> > + int ra_regnum; /* Return address. */
>> > + int ps_regnum; /* Processor status. */
>> > + int hi_regnum; /* High portion of internal multiply/divide
>> > + register. */
>> > + int lo_regnum; /* Low portion of internal multiply/divide
>> > + register. */
>> > + int badvaddr_regnum; /* Address associated with
>> > + addressing exception. */
>> > + int cause_regnum; /* Describes last exception. */
>> > + int pc_regnum; /* Program counter. */
>> > + int fcrcs_regnum; /* FP control/status. */
>> > + int fcrir_regnum; /* FP implementation/revision. */
>> > + int first_embed_regnum; /* First CP0 register for embedded use. */
>> > + int last_embed_regnum; /* Last CP0 register for embedded use. */
>> > + int prid_regnum; /* Processor ID. */
>> > + };
>> > +
>> > +const struct mips_regnums *mips_raw_regnums (struct gdbarch *gdbarch);
>> > +const struct mips_regnums *mips_cooked_regnums (struct gdbarch *gdbarch);
>
>>
>> or at least keep things like "last_arg_regnum" out this space (they only
>> belong in one of the two spaces). Having them appear in both makes it
>> too easy to do the wrong thing.
>
>
> Actually, I think it's useful for the layout raw and cooked regnum
> structs to be identical. When initializing the cooked regnum struct,
> we can do so via a single assignment:
>
> /* For many registers, the cooked and raw register numbers are the same. */
> tdep->cooked_regnums = tdep->raw_regnums;
>
> /* Cooked regnum initializations that differ follow... */
>
> The fact that the structs were identical made it easy and elegant to
> define the reg_name() function which is used twice by mips_register_name(),
> once for cooked register numbers, and a second time (assuming no suitable
> cooked name was found) for the raw numbers. If the layout of the cooked
> and raw structs were different, I'd need two separate functions with nearly
> identical functionality. Ditto for mips_dump_regnums().
>
> I think that you definitely want "last_arg_regnum" and
> "last_fp_arg_regnum" to appear in both structs. At the moment, the
> various MIPS *_push_argument() code uses the register names from the
> raw regnums struct. I think it may be desirable at some point to make
> this code use cooked regnums instead. (It will hopefully simplify a
> bunch of code that worries about shifting values to the correct
> position within a register.) For the floating point registers, where
> the cooked and raw numbers are actually different, we would like
> "first_fp_arg_regnum" and "last_fp_arg_regnum" to actually refer to
> numbers within this space.
The only code that should manipulate the raw register values
(regcache_raw_*) is:
- the cooked <-> raw mapping functions
- the target side code that supplies register values
The rest should use cooked values. Hence, I think the variables like
last_arg_regnum has a strictly cooked value (note that a cooked register
number can fall in the range [0 .. NUM_REGS).
>> How do you know that the raw register numbers were computed correctly?
>
>
> I just used the same values as the macros used to use. The user can see
> what they are via "maint print architecture".
I'm wondering how you know that the transformation from macro (defined
in .h files?) to variables worked?
Andrew
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-16 4:00 ` Andrew Cagney
@ 2003-05-16 17:20 ` Kevin Buettner
[not found] ` <mailpost.1053057614.17325@news-sj1-1>
1 sibling, 0 replies; 46+ messages in thread
From: Kevin Buettner @ 2003-05-16 17:20 UTC (permalink / raw)
To: Andrew Cagney; +Cc: gdb-patches
On May 15, 11:57pm, Andrew Cagney wrote:
> >> > BTW, the raw floating point registers are still accessible. Doing
> >> > "info registers raw" will display all of the raw registers. Or, if
> >> > you know the names of the registers you want to display, you can do,
> >> > e.g, "info registers raw_f20".
> >
> >>
> >> Hmm, is this necessary? Confusing? ``maint print
> >> {raw-,cooked-,}registers'' are already available and provide access to
> >> the underlying values.
> >
> >
> > Maybe we need to name the prefix something different than "raw_"?
> >
> > Whatever we call them, I think it's still useful to have names
> > associated with them. E.g, you can do any of the following:
> >
> > print $raw_f20
> > print/x ($raw_f20 >> 32)
> > set $raw_f20=0xbadbeef
>
> But how often will that actually happen?
Personally, I don't think that it'll happen that often. If, however,
the 32 unpredictable bits of a floating point register (for o32) are
meaningful, it may be useful to be able to manipulate the raw register
in various ways.
> I think a user debugging o32 on ISA64 still should expect to be
> manipulating the full 64 bit register.
I disagree. When debugging o32, the FR bit in the CP0 status register
should be 0 and, according to the MIPS64 documentation, the FPRs are
treated as 32 32-bit registers.
> Only on ISA32 should the
> registers be restricted to their 32 bit values.
>
> Even if the upper 32 bits of the FP registers are unpredictable, I think
> they should still be displayed.
With my WIP patch, for o32 single precision code, you'll something like
this:
(gdb) p $f20
$2 = {i = 18446744070510660813, f = 13.3000002, d = -nan(0xfffff4154cccd)}
For double precision code, you'll instead see:
(gdb) p $f20
$3 = {i = 4623676852435261850, f = -1.58818684e-23, d = 13.300000000000001}
where the 13.3 value in both cases is the value of interest.
If I were to do as you suggest and display the full 64 bits of the raw
f20, you'd never be able to see that interesting 13.3 value for the
double case. (This is because the bits which form the double are
split between raw f20 and raw f21.) The user should expect to see
values which make sense for the mode of the processor. As I said
before, if the user suspects that something else is going on, they
still have recourse to $raw_f20 and $raw_f21 for looking at the full
64-bit register. E.g.:
(gdb) p/x $raw_f20
$5 = 0xffffffff9999999a
(gdb) p/x $raw_f21
$6 = 0x402a9999
And, for reference:
(gdb) p/x $f20.i
$7 = 0x402a99999999999a
If you really think that the $f20 name should be the full 64-bit register
regardless of the fact that 32-bits are meaningless, then lets just take
the "raw_" prefix off of them and put a prefix on the cooked names. Maybe
we should call them "cooked_f20" or "pretty_f20" or some such.
I do agree that we want to provide the user with the ability to look
at the full 64-bit value, but I think it's also important that the
user be able to see values that make the most sense for the mode that
the processor is in. My WIP patch provides you with the ability to
see both. It sounds like you may have an objection to the names that
I've chosen. If that's the case, then I'm willing to discard the
"raw_" prefix on the raw floating point registers and put a different
prefix on the cooked fp registers.
[...]
> > I think that you definitely want "last_arg_regnum" and
> > "last_fp_arg_regnum" to appear in both structs. At the moment, the
> > various MIPS *_push_argument() code uses the register names from the
> > raw regnums struct. I think it may be desirable at some point to make
> > this code use cooked regnums instead. (It will hopefully simplify a
> > bunch of code that worries about shifting values to the correct
> > position within a register.) For the floating point registers, where
> > the cooked and raw numbers are actually different, we would like
> > "first_fp_arg_regnum" and "last_fp_arg_regnum" to actually refer to
> > numbers within this space.
>
> The only code that should manipulate the raw register values
> (regcache_raw_*) is:
> - the cooked <-> raw mapping functions
> - the target side code that supplies register values
> The rest should use cooked values. Hence, I think the variables like
> last_arg_regnum has a strictly cooked value (note that a cooked register
> number can fall in the range [0 .. NUM_REGS).
Well, ideally, yes. But, I think it's going to be a while before we
get there. As a specific example, consider the various MIPS
push_arguments code. At the present time, this code is written to use
raw numbers and will need to be converted at some point to use cooked
numbers. For last_fp_arg_regnum, the raw and cooked numbers will
differ, and, I expect that the various push_arguments functions will
be converted incrementally, so it is important that this field appear
in both structs. (I should note that I have this detail wrong in my
WIP patch. I forgot to set the cooked value for last_fp_arg_regnum.
That means that the cooked value is the same as the raw value which is
wrong.)
I will also note that since last_fp_arg_regnum is _only_ used by the
push_arguments code, it would be possible to seperate this value out,
BUT, it will be necessary for the code which initializes
last_fp_arg_regnum to keep track of whether or not the appropriate
push_arguments function has been converted or not. mips_gdbarch_init()
will need to be rearranged somewhat in order for this to occur.
> >> How do you know that the raw register numbers were computed correctly?
> >
> >
> > I just used the same values as the macros used to use. The user can see
> > what they are via "maint print architecture".
>
> I'm wondering how you know that the transformation from macro (defined
> in .h files?) to variables worked?
By inspection and by testing.
Kevin
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
[not found] ` <mailpost.1053057614.17325@news-sj1-1>
@ 2003-05-16 22:25 ` cgd
[not found] ` <mailpost.1053123913.16634@news-sj1-1>
0 siblings, 1 reply; 46+ messages in thread
From: cgd @ 2003-05-16 22:25 UTC (permalink / raw)
To: ac131313; +Cc: Kevin Buettner, gdb-patches
At Fri, 16 May 2003 04:00:14 +0000 (UTC), "Andrew Cagney" wrote:
> > Whatever we call them, I think it's still useful to have names
> > associated with them. E.g, you can do any of the following:
> >
> > print $raw_f20
> > print/x ($raw_f20 >> 32)
> > set $raw_f20=0xbadbeef
>
> But how often will that actually happen?
>
> I think a user debugging o32 on ISA64 still should expect to be
> manipulating the full 64 bit register. Only on ISA32 should the
> registers be restricted to their 32 bit values.
>
> Even if the upper 32 bits of the FP registers are unpredictable, I think
> they should still be displayed.
I assume you're talking about manipulating the full 64-bits *only* for
the raw values. I think there may be issues there, when FR == 0.
When FR == 0, reading and writing doubles from the odd registers in
unpredictable, and reading/writing doubles from the even registers **
must ** include the odd-register value.
So, for instance, when FR = 0, if you read 64 bits of $f12, you'll
get:
$f12: 0xaaaaaaaabbbbbbbb
That's guarateed.
if you read a single from $f12, you'll get 0xbbbbbbbb, a single from
$f13 you'll get 0xaaaaaaaa. Likewise, guaranteed.
but if you read a double from $f13, who *knows* what you're going to
get. You might get:
$f13: 0x????????aaaaaaaa
but who really knows, and who knows what the ???????? is.
(I think i got my word ordering right in that description. 8-)
When FR==0, there are only two valid ways to read the registers:
* for i = 0; i < 32; i++
<read 32-bits from $i>
* for i = 0; i < 32; i += 2
<read 64-bits from $i>
This MIPS specifications (M64 1.00 Volume I, page 50, section 5.6.2)
indicate that doing 64-bit reads/writes from/to odd FP registers when
FR=0 are "illegal", and that values produced by such operations are
unpredictable.
In other words, if a 64-bit target stub code really is supplying 64
bits of register data when accessing FP registers when FR == 0, then
it's broken.
(If it's attempting to write the odd 64-bit register values back, then
it's *really* broken.)
Heck, if 64-bit target code is even trying to communicate (64 * 8)
bits back when FR == 0, then it's almost certainly broken. (every
other reigster will be completely unpredictable, and who knows what'll
happen if it tries to write them back if they're changed.)
As an aside, it would probably be good if, when setting a fp register,
e.g.:
set $f12 = <value>
you were *required* to use one of the union members.
it's kinda weird (uh, quite confusing 8-) to see something like:
(gdb) info args
a = -nan(0x7fffff)
b = 2.20000005
c = 3.29999995
d = -4.4000001
(gdb) info addr b
Symbol "b" is an argument in register f13.
(gdb) set $f13 = 3.3
(gdb) info args
a = -nan(0x7fffff)
b = 2.72008302e+23
c = 3.29999995
d = -4.4000001
i.e., blind conversion (because "set $f13 = <value>" assumed
incorrectly that you meant "oh, as double") is bad.
(If you're in the situation where you're setting an even register to a
single value, if the n+1 odd reigster also a single value you also
want to do computation on, setting the even as a double could be even
worse...)
cgd
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
[not found] ` <mailpost.1053123913.16634@news-sj1-1>
@ 2003-05-16 22:50 ` cgd
2003-05-16 23:05 ` Kevin Buettner
2003-05-20 20:25 ` Andrew Cagney
0 siblings, 2 replies; 46+ messages in thread
From: cgd @ 2003-05-16 22:50 UTC (permalink / raw)
To: ac131313; +Cc: Kevin Buettner, gdb-patches
At Fri, 16 May 2003 22:25:13 +0000 (UTC), cgd@broadcom.com wrote:
> This MIPS specifications (M64 1.00 Volume I, page 50, section 5.6.2)
> indicate that doing 64-bit reads/writes from/to odd FP registers when
> FR=0 are "illegal", and that values produced by such operations are
> unpredictable.
Actually, on the reads they say that the values produced are
unpredictable.
For writes, they indicate that the operation itself is unpredictable
("UNPREDICTABLE").
in other words, doing an ldc1 when FR == 0 could cause a trap if an
implementation were paranoid (*cough* simulator 8-).
So, really, when FR == 0, best to think of yourself as having only 32
* 32 bits.
Now, the question is, in the remote protocol, if 64-bit registers are
being passed, *how*. (64-bit target, normally 64-bit registers... i'd assume
they're being passed as 64-bits.)
One reasonable way to do it, which i believe would be the result of
using n32 / n64 RDA on linux to debug an o32 executable, would be:
0: meaningful
1: garbage
etc.
this is the natural way to do it on a 64-bit part, with a 64-bit FPU.
another reasonable way (but less efficient on a 64-bit part with a
64-bit FPU) would be:
0: <high half garbage><low half meaningful>
1: <high half garbage><low half meaningful>
Are there 64-bit parts out there that have FPUs with 32 single float
regs which one can operate on (4650, looking at gcc srcs?) If so, the
latter would be a reasonable representation for them.
So, my conclusion is:
for raw registers that are xferred as 64-bits, yeah, fine, let people
have acess to them. that's for debugger-debugging, and people who
muck with them may be shooting themselves in the head, but if they're
debugging the debugger they're smart, right? 8-)
need to have some way to tell which of the ways above is being used to
xfer the register data. (or, need to define that only one way may be
used.)
chris
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-16 22:50 ` cgd
@ 2003-05-16 23:05 ` Kevin Buettner
[not found] ` <mailpost.1053126410.17856@news-sj1-1>
2003-05-20 20:25 ` Andrew Cagney
1 sibling, 1 reply; 46+ messages in thread
From: Kevin Buettner @ 2003-05-16 23:05 UTC (permalink / raw)
To: cgd, ac131313; +Cc: Kevin Buettner, gdb-patches
On May 16, 3:50pm, cgd@broadcom.com wrote:
> another reasonable way (but less efficient on a 64-bit part with a
> 64-bit FPU) would be:
>
> 0: <high half garbage><low half meaningful>
> 1: <high half garbage><low half meaningful>
This is how the mips64 o32 rda transfers the FP registers.
Kevin
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
[not found] ` <mailpost.1053126410.17856@news-sj1-1>
@ 2003-05-16 23:24 ` cgd
2003-05-17 0:41 ` Kevin Buettner
0 siblings, 1 reply; 46+ messages in thread
From: cgd @ 2003-05-16 23:24 UTC (permalink / raw)
To: kevinb; +Cc: ac131313, gdb-patches
At Fri, 16 May 2003 23:06:50 +0000 (UTC), "Kevin Buettner" wrote:
> On May 16, 3:50pm, cgd@broadcom.com wrote:
>
> > another reasonable way (but less efficient on a 64-bit part with a
> > 64-bit FPU) would be:
> >
> > 0: <high half garbage><low half meaningful>
> > 1: <high half garbage><low half meaningful>
>
> This is how the mips64 o32 rda transfers the FP registers.
Hmm.
OK, then, well, how do we ("gdb") tell the difference, since for o32
binaries it's reasonable to use either o32 RDA or (one might think)
n32 RDA?
8-)
chris
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-16 23:24 ` cgd
@ 2003-05-17 0:41 ` Kevin Buettner
2003-05-17 20:59 ` Daniel Jacobowitz
[not found] ` <mailpost.1053132070.20348@news-sj1-1>
0 siblings, 2 replies; 46+ messages in thread
From: Kevin Buettner @ 2003-05-17 0:41 UTC (permalink / raw)
To: cgd, kevinb; +Cc: ac131313, gdb-patches
On May 16, 4:24pm, cgd@broadcom.com wrote:
> At Fri, 16 May 2003 23:06:50 +0000 (UTC), "Kevin Buettner" wrote:
> > On May 16, 3:50pm, cgd@broadcom.com wrote:
> >
> > > another reasonable way (but less efficient on a 64-bit part with a
> > > 64-bit FPU) would be:
> > >
> > > 0: <high half garbage><low half meaningful>
> > > 1: <high half garbage><low half meaningful>
> >
> > This is how the mips64 o32 rda transfers the FP registers.
>
> Hmm.
>
> OK, then, well, how do we ("gdb") tell the difference, since for o32
> binaries it's reasonable to use either o32 RDA or (one might think)
> n32 RDA?
Unfortunately, it isn't reasonable to use an ABI-specific RDA to debug
an application which uses a different ABI. It might kind of, sort of
work some of the time, but there are various things that won't work.
You've just identified one of the problems.
Another one (and it's a doozie) is that thread debugging won't work
due to the ABI specific libthread_db.so library that's dlopen'd by
RDA. A native GDB (assuming that we did the necessary work to port it
to mips64-linux) would have the same problem. We've kicked around
some ideas for fixing this problem in the past. The only idea that
I've found compelling is from Alex Oliva (and perhaps others) who
suggested that it may be best for a "native" gdb to spawn an
ABI-specific rda or gdbserver and connect to it automatically.
Kevin
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-17 0:41 ` Kevin Buettner
@ 2003-05-17 20:59 ` Daniel Jacobowitz
2003-05-20 20:18 ` Always remote: " Andrew Cagney
[not found] ` <mailpost.1053132070.20348@news-sj1-1>
1 sibling, 1 reply; 46+ messages in thread
From: Daniel Jacobowitz @ 2003-05-17 20:59 UTC (permalink / raw)
To: Kevin Buettner; +Cc: cgd, ac131313, gdb-patches
On Fri, May 16, 2003 at 05:40:52PM -0700, Kevin Buettner wrote:
> On May 16, 4:24pm, cgd@broadcom.com wrote:
>
> > At Fri, 16 May 2003 23:06:50 +0000 (UTC), "Kevin Buettner" wrote:
> > > On May 16, 3:50pm, cgd@broadcom.com wrote:
> > >
> > > > another reasonable way (but less efficient on a 64-bit part with a
> > > > 64-bit FPU) would be:
> > > >
> > > > 0: <high half garbage><low half meaningful>
> > > > 1: <high half garbage><low half meaningful>
> > >
> > > This is how the mips64 o32 rda transfers the FP registers.
> >
> > Hmm.
> >
> > OK, then, well, how do we ("gdb") tell the difference, since for o32
> > binaries it's reasonable to use either o32 RDA or (one might think)
> > n32 RDA?
>
> Unfortunately, it isn't reasonable to use an ABI-specific RDA to debug
> an application which uses a different ABI. It might kind of, sort of
> work some of the time, but there are various things that won't work.
> You've just identified one of the problems.
>
> Another one (and it's a doozie) is that thread debugging won't work
> due to the ABI specific libthread_db.so library that's dlopen'd by
> RDA. A native GDB (assuming that we did the necessary work to port it
> to mips64-linux) would have the same problem. We've kicked around
> some ideas for fixing this problem in the past. The only idea that
> I've found compelling is from Alex Oliva (and perhaps others) who
> suggested that it may be best for a "native" gdb to spawn an
> ABI-specific rda or gdbserver and connect to it automatically.
TBH, I'd rather like to see us develop an extended and more extensible
remote protocol (on any number of people's TODO lists already!) and do
_all_ native debugging this way.
I don't think it's a pipe dream but it's definitely a future dream.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Always remote: [WIP/RFC] MIPS registers overhaul
2003-05-17 20:59 ` Daniel Jacobowitz
@ 2003-05-20 20:18 ` Andrew Cagney
2003-05-20 20:26 ` Daniel Jacobowitz
0 siblings, 1 reply; 46+ messages in thread
From: Andrew Cagney @ 2003-05-20 20:18 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Kevin Buettner, cgd, gdb-patches
>> Another one (and it's a doozie) is that thread debugging won't work
>> due to the ABI specific libthread_db.so library that's dlopen'd by
>> RDA. A native GDB (assuming that we did the necessary work to port it
>> to mips64-linux) would have the same problem. We've kicked around
>> some ideas for fixing this problem in the past. The only idea that
>> I've found compelling is from Alex Oliva (and perhaps others) who
>> suggested that it may be best for a "native" gdb to spawn an
>> ABI-specific rda or gdbserver and connect to it automatically.
>
>
> TBH, I'd rather like to see us develop an extended and more extensible
> remote protocol (on any number of people's TODO lists already!) and do
> _all_ native debugging this way.
FYI, one of the long ago identified scalability problems (by HP) with
GDB was all the memory moving/sucking that it did. HP were looking for
ways to MMAP memory and avoiding doing all the copies. Having GDB suck
memory through a straw would be a odds with that.
Note, I'm talking here about megabytes of memory - people try to use the
debuger to draw plots of their fortran arrays.
Andrew
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-16 22:50 ` cgd
2003-05-16 23:05 ` Kevin Buettner
@ 2003-05-20 20:25 ` Andrew Cagney
2003-05-20 20:32 ` cgd
1 sibling, 1 reply; 46+ messages in thread
From: Andrew Cagney @ 2003-05-20 20:25 UTC (permalink / raw)
To: cgd, Kevin Buettner; +Cc: gdb-patches
> At Fri, 16 May 2003 22:25:13 +0000 (UTC), cgd@broadcom.com wrote:
>
>> This MIPS specifications (M64 1.00 Volume I, page 50, section 5.6.2)
>> indicate that doing 64-bit reads/writes from/to odd FP registers when
>> FR=0 are "illegal", and that values produced by such operations are
>> unpredictable.
>
>
> Actually, on the reads they say that the values produced are
> unpredictable.
>
> For writes, they indicate that the operation itself is unpredictable
> ("UNPREDICTABLE").
When a 64 bit kernel goes to save/resume an o32 process, how does it do
it? Does it have a choice?
For instance, do a 64 bit FP restore then clear the FR bit; the reverse;
some other variant; ...?
Andrew
> in other words, doing an ldc1 when FR == 0 could cause a trap if an
> implementation were paranoid (*cough* simulator 8-).
>
> So, really, when FR == 0, best to think of yourself as having only 32
> * 32 bits.
>
>
> Now, the question is, in the remote protocol, if 64-bit registers are
> being passed, *how*. (64-bit target, normally 64-bit registers... i'd assume
> they're being passed as 64-bits.)
>
> One reasonable way to do it, which i believe would be the result of
> using n32 / n64 RDA on linux to debug an o32 executable, would be:
>
> 0: meaningful
> 1: garbage
> etc.
>
> this is the natural way to do it on a 64-bit part, with a 64-bit FPU.
> another reasonable way (but less efficient on a 64-bit part with a
> 64-bit FPU) would be:
>
> 0: <high half garbage><low half meaningful>
> 1: <high half garbage><low half meaningful>
>
> Are there 64-bit parts out there that have FPUs with 32 single float
> regs which one can operate on (4650, looking at gcc srcs?) If so, the
> latter would be a reasonable representation for them.
>
>
> So, my conclusion is:
>
> for raw registers that are xferred as 64-bits, yeah, fine, let people
> have acess to them. that's for debugger-debugging, and people who
> muck with them may be shooting themselves in the head, but if they're
> debugging the debugger they're smart, right? 8-)
>
> need to have some way to tell which of the ways above is being used to
> xfer the register data. (or, need to define that only one way may be
> used.)
>
>
> chris
>
>
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Always remote: [WIP/RFC] MIPS registers overhaul
2003-05-20 20:18 ` Always remote: " Andrew Cagney
@ 2003-05-20 20:26 ` Daniel Jacobowitz
0 siblings, 0 replies; 46+ messages in thread
From: Daniel Jacobowitz @ 2003-05-20 20:26 UTC (permalink / raw)
To: Andrew Cagney; +Cc: Kevin Buettner, cgd, gdb-patches
On Tue, May 20, 2003 at 04:17:51PM -0400, Andrew Cagney wrote:
>
> >>Another one (and it's a doozie) is that thread debugging won't work
> >>due to the ABI specific libthread_db.so library that's dlopen'd by
> >>RDA. A native GDB (assuming that we did the necessary work to port it
> >>to mips64-linux) would have the same problem. We've kicked around
> >>some ideas for fixing this problem in the past. The only idea that
> >>I've found compelling is from Alex Oliva (and perhaps others) who
> >>suggested that it may be best for a "native" gdb to spawn an
> >>ABI-specific rda or gdbserver and connect to it automatically.
> >
> >
> >TBH, I'd rather like to see us develop an extended and more extensible
> >remote protocol (on any number of people's TODO lists already!) and do
> >_all_ native debugging this way.
>
> FYI, one of the long ago identified scalability problems (by HP) with
> GDB was all the memory moving/sucking that it did. HP were looking for
> ways to MMAP memory and avoiding doing all the copies. Having GDB suck
> memory through a straw would be a odds with that.
>
> Note, I'm talking here about megabytes of memory - people try to use the
> debuger to draw plots of their fortran arrays.
Definitely something to keep in mind... but I think not necessarily in
conflict.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-20 20:25 ` Andrew Cagney
@ 2003-05-20 20:32 ` cgd
2003-05-21 15:40 ` Andrew Cagney
2003-06-15 17:23 ` Andrew Cagney
0 siblings, 2 replies; 46+ messages in thread
From: cgd @ 2003-05-20 20:32 UTC (permalink / raw)
To: Andrew Cagney; +Cc: Kevin Buettner, gdb-patches
At Tue, 20 May 2003 16:23:34 -0400, Andrew Cagney wrote:
> When a 64 bit kernel goes to save/resume an o32 process, how does it do
> it? Does it have a choice?
it has limited choice.
> For instance, do a 64 bit FP restore then clear the FR bit; the reverse;
> some other variant; ...?
So, if the process is running with FR=0, then the save/restore should
("must" i believe) be done with FR=0.
When FR=0, there are two options as to how to do it:
for (i = 0; i < 32; i++)
move/store word from c1 reg $i (i.e., dmfc1/sdc1)
OR:
for (i = 0; i < 32; i += 2)
move/store dword from c1 reg $i (i.e., dmfc1/sdc1)
(move to / load for the state restore, of course.)
(of course, these will typically be written in assembly code, and
"fully unrolled" -- the pseudo-C-code is to demonstrate the concept
only.)
either one is valid, though all implementations that I know of choose
the latter because it's fewer instructions and almost certainly more
efficient.
the linux kernel presents that to o32 userland (o32 ptrace syscall) as
an array of 32 32-bit values, but IIRC it's stored internally as (8
byte reg, 8 byte pad) * 16.
cgd
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
[not found] ` <mailpost.1053132070.20348@news-sj1-1>
@ 2003-05-20 20:37 ` cgd
2003-05-20 20:51 ` Kevin Buettner
2003-05-20 20:52 ` Andrew Cagney
0 siblings, 2 replies; 46+ messages in thread
From: cgd @ 2003-05-20 20:37 UTC (permalink / raw)
To: kevinb; +Cc: ac131313, gdb-patches
At Sat, 17 May 2003 00:41:10 +0000 (UTC), "Kevin Buettner" wrote:
> Unfortunately, it isn't reasonable to use an ABI-specific RDA to debug
> an application which uses a different ABI. It might kind of, sort of
> work some of the time, but there are various things that won't work.
> You've just identified one of the problems.
BTW, because of this kind of problem, does it even make sense that
when talking to a mips64 kernel but using an o32 rda (or gdbserver
8-), you'd use a "mips64" protocol? I.e., why wouldn't it just use
the 32-bit mips protocol, since from you're debugging a 32-bit binary
with a 32-bit debugging daemon...
Yeah, the kernel's 64 bits, but that's pretty much irrelevant...
cgd
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-20 20:37 ` cgd
@ 2003-05-20 20:51 ` Kevin Buettner
2003-05-20 20:52 ` Andrew Cagney
1 sibling, 0 replies; 46+ messages in thread
From: Kevin Buettner @ 2003-05-20 20:51 UTC (permalink / raw)
To: cgd, kevinb; +Cc: ac131313, gdb-patches
On May 20, 1:37pm, cgd@broadcom.com wrote:
> At Sat, 17 May 2003 00:41:10 +0000 (UTC), "Kevin Buettner" wrote:
> > Unfortunately, it isn't reasonable to use an ABI-specific RDA to debug
> > an application which uses a different ABI. It might kind of, sort of
> > work some of the time, but there are various things that won't work.
> > You've just identified one of the problems.
>
> BTW, because of this kind of problem, does it even make sense that
> when talking to a mips64 kernel but using an o32 rda (or gdbserver
> 8-), you'd use a "mips64" protocol? I.e., why wouldn't it just use
> the 32-bit mips protocol, since from you're debugging a 32-bit binary
> with a 32-bit debugging daemon...
Unfortunately, with the way things are (still) layed out for MIPS, if
you want a single GDB executable to be able to debug both 64- and 32-bit
code, it needs to use the same register width for the remote protocol.
Assuming that my recently proposed MIPS overhaul actually gets in,
we're closer to being able to dynamically change this so that a single
GDB binary can use either protocol. The constant MIPS_REGSIZE will
need to be changed so that it can be set to be either 4 or 8...
I think I have the code in a state now where this shouldn't be hard to
do.
Kevin
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-20 20:37 ` cgd
2003-05-20 20:51 ` Kevin Buettner
@ 2003-05-20 20:52 ` Andrew Cagney
2003-05-20 21:57 ` cgd
1 sibling, 1 reply; 46+ messages in thread
From: Andrew Cagney @ 2003-05-20 20:52 UTC (permalink / raw)
To: cgd; +Cc: kevinb, gdb-patches
> At Sat, 17 May 2003 00:41:10 +0000 (UTC), "Kevin Buettner" wrote:
>
>> Unfortunately, it isn't reasonable to use an ABI-specific RDA to debug
>> an application which uses a different ABI. It might kind of, sort of
>> work some of the time, but there are various things that won't work.
>> You've just identified one of the problems.
>
>
> BTW, because of this kind of problem, does it even make sense that
> when talking to a mips64 kernel but using an o32 rda (or gdbserver
> 8-), you'd use a "mips64" protocol? I.e., why wouldn't it just use
> the 32-bit mips protocol, since from you're debugging a 32-bit binary
> with a 32-bit debugging daemon...
Ignoring the FP registers, I think it does make sense. o32 code does
run on a 64 bit ISA. Who is GDB to decide what the ISA should be.
Andrew
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-20 20:52 ` Andrew Cagney
@ 2003-05-20 21:57 ` cgd
2003-05-21 15:34 ` Andrew Cagney
0 siblings, 1 reply; 46+ messages in thread
From: cgd @ 2003-05-20 21:57 UTC (permalink / raw)
To: Andrew Cagney; +Cc: kevinb, gdb-patches
At Tue, 20 May 2003 16:52:23 -0400, Andrew Cagney wrote:
> > At Sat, 17 May 2003 00:41:10 +0000 (UTC), "Kevin Buettner" wrote:
> >
> >> Unfortunately, it isn't reasonable to use an ABI-specific RDA to debug
> >> an application which uses a different ABI. It might kind of, sort of
> >> work some of the time, but there are various things that won't work.
> >> You've just identified one of the problems.
> >
> >
> > BTW, because of this kind of problem, does it even make sense that
> > when talking to a mips64 kernel but using an o32 rda (or gdbserver
> > 8-), you'd use a "mips64" protocol? I.e., why wouldn't it just use
> > the 32-bit mips protocol, since from you're debugging a 32-bit binary
> > with a 32-bit debugging daemon...
>
> Ignoring the FP registers, I think it does make sense. o32 code does
> run on a 64 bit ISA. Who is GDB to decide what the ISA should be.
I think even w.r.t. FP registers it makes sense. 8-)
in o32, there are exactly (32 * 32 bits) worth of FP registers.
They've got a very strange organization, and different operations on
them set them in non-obvious ways, but they're still 32*32 bits.
cgd
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-20 21:57 ` cgd
@ 2003-05-21 15:34 ` Andrew Cagney
2003-05-21 15:41 ` Daniel Jacobowitz
0 siblings, 1 reply; 46+ messages in thread
From: Andrew Cagney @ 2003-05-21 15:34 UTC (permalink / raw)
To: cgd, kevinb; +Cc: gdb-patches
> At Tue, 20 May 2003 16:52:23 -0400, Andrew Cagney wrote:
>
>> > At Sat, 17 May 2003 00:41:10 +0000 (UTC), "Kevin Buettner" wrote:
>> >
>
>> >> Unfortunately, it isn't reasonable to use an ABI-specific RDA to debug
>> >> an application which uses a different ABI. It might kind of, sort of
>> >> work some of the time, but there are various things that won't work.
>> >> You've just identified one of the problems.
>
>> >
>> >
>> > BTW, because of this kind of problem, does it even make sense that
>> > when talking to a mips64 kernel but using an o32 rda (or gdbserver
>> > 8-), you'd use a "mips64" protocol? I.e., why wouldn't it just use
>> > the 32-bit mips protocol, since from you're debugging a 32-bit binary
>> > with a 32-bit debugging daemon...
>
>>
>> Ignoring the FP registers, I think it does make sense. o32 code does
>> run on a 64 bit ISA. Who is GDB to decide what the ISA should be.
That came out wrong.
I think a GDB debugging a remote 64 bit MIPS ISA should always expect 64
bit GPRs and 64 bit FPRs when the ISA is 64 bits, regardless of the ABI.
It is quite legitimate, for instance, for GDB to do something as sick-o
as clearing the FR bit and then resume the thread. The register
save/restore code needs to correctly handle this - be it reject the
operation or ``do the right thing''.
Andrew
> I think even w.r.t. FP registers it makes sense. 8-)
>
> in o32, there are exactly (32 * 32 bits) worth of FP registers.
>
> They've got a very strange organization, and different operations on
> them set them in non-obvious ways, but they're still 32*32 bits.
>
>
>
> cgd
>
>
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-20 20:32 ` cgd
@ 2003-05-21 15:40 ` Andrew Cagney
2003-06-15 1:44 ` Andrew Cagney
2003-06-15 17:23 ` Andrew Cagney
1 sibling, 1 reply; 46+ messages in thread
From: Andrew Cagney @ 2003-05-21 15:40 UTC (permalink / raw)
To: cgd; +Cc: Kevin Buettner, gdb-patches
> At Tue, 20 May 2003 16:23:34 -0400, Andrew Cagney wrote:
>
>> When a 64 bit kernel goes to save/resume an o32 process, how does it do
>> it? Does it have a choice?
>
>
> it has limited choice.
>
>
>
>> For instance, do a 64 bit FP restore then clear the FR bit; the reverse;
>> some other variant; ...?
>
>
> So, if the process is running with FR=0, then the save/restore should
> ("must" i believe) be done with FR=0.
>
> When FR=0, there are two options as to how to do it:
>
> for (i = 0; i < 32; i++)
> move/store word from c1 reg $i (i.e., dmfc1/sdc1)
>
> OR:
>
> for (i = 0; i < 32; i += 2)
> move/store dword from c1 reg $i (i.e., dmfc1/sdc1)
That isn't quite the detail I was looking for. Does the code need to
look like:
save::
save FSR
if (FSR & FR)
save 32x32 FP
else
save 32x64 FP
restore::
restore FSR
if (FSR & FR)
restore 32x32 FP
else
restore 32x64 FP
that is, the FSR[FR] bit (wonder if I've got the names right) needs to
set/clear the FR bit before it even starts to consider saving/restoring
the other registers. The reverse operation:
save::
save FSR
make FP registers 64 bit
save 32x64 FP
restore::
// assume FSR[FR] set to 64 bit mode
restore 32x64 FP
restore FSR
operation not being valid.
Andrew
> (move to / load for the state restore, of course.)
>
> (of course, these will typically be written in assembly code, and
> "fully unrolled" -- the pseudo-C-code is to demonstrate the concept
> only.)
>
> either one is valid, though all implementations that I know of choose
> the latter because it's fewer instructions and almost certainly more
> efficient.
>
>
> the linux kernel presents that to o32 userland (o32 ptrace syscall) as
> an array of 32 32-bit values, but IIRC it's stored internally as (8
> byte reg, 8 byte pad) * 16.
>
>
>
> cgd
>
>
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-21 15:34 ` Andrew Cagney
@ 2003-05-21 15:41 ` Daniel Jacobowitz
2003-05-21 16:38 ` Andrew Cagney
0 siblings, 1 reply; 46+ messages in thread
From: Daniel Jacobowitz @ 2003-05-21 15:41 UTC (permalink / raw)
To: Andrew Cagney; +Cc: cgd, kevinb, gdb-patches
On Wed, May 21, 2003 at 11:34:39AM -0400, Andrew Cagney wrote:
> >At Tue, 20 May 2003 16:52:23 -0400, Andrew Cagney wrote:
> >
> >>> At Sat, 17 May 2003 00:41:10 +0000 (UTC), "Kevin Buettner" wrote:
> >>>
> >
> >>>> Unfortunately, it isn't reasonable to use an ABI-specific RDA to debug
> >>>> an application which uses a different ABI. It might kind of, sort of
> >>>> work some of the time, but there are various things that won't work.
> >>>> You've just identified one of the problems.
> >
> >>>
> >>>
> >>> BTW, because of this kind of problem, does it even make sense that
> >>> when talking to a mips64 kernel but using an o32 rda (or gdbserver
> >>> 8-), you'd use a "mips64" protocol? I.e., why wouldn't it just use
> >>> the 32-bit mips protocol, since from you're debugging a 32-bit binary
> >>> with a 32-bit debugging daemon...
> >
> >>
> >>Ignoring the FP registers, I think it does make sense. o32 code does
> >>run on a 64 bit ISA. Who is GDB to decide what the ISA should be.
>
> That came out wrong.
>
> I think a GDB debugging a remote 64 bit MIPS ISA should always expect 64
> bit GPRs and 64 bit FPRs when the ISA is 64 bits, regardless of the ABI.
>
> It is quite legitimate, for instance, for GDB to do something as sick-o
> as clearing the FR bit and then resume the thread. The register
> save/restore code needs to correctly handle this - be it reject the
> operation or ``do the right thing''.
But when using rda or gdbserver to debug an o32 application, then for
all intents and purposes we are debugging a 32-bit ISA. The kernel
will not allow us to change the FR bit. The app will never see 64-bit
registers. The 32-bit protocol makes more sense here IMO.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-21 15:41 ` Daniel Jacobowitz
@ 2003-05-21 16:38 ` Andrew Cagney
2003-05-21 16:58 ` Daniel Jacobowitz
0 siblings, 1 reply; 46+ messages in thread
From: Andrew Cagney @ 2003-05-21 16:38 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: cgd, kevinb, gdb-patches
>> That came out wrong.
>>
>> I think a GDB debugging a remote 64 bit MIPS ISA should always expect 64
>> bit GPRs and 64 bit FPRs when the ISA is 64 bits, regardless of the ABI.
>>
>> It is quite legitimate, for instance, for GDB to do something as sick-o
>> as clearing the FR bit and then resume the thread. The register
>> save/restore code needs to correctly handle this - be it reject the
>> operation or ``do the right thing''.
>
>
> But when using rda or gdbserver to debug an o32 application, then for
> all intents and purposes we are debugging a 32-bit ISA. The kernel
> will not allow us to change the FR bit. The app will never see 64-bit
> registers. The 32-bit protocol makes more sense here IMO.
From GDB's view point, the ISA is 64 bit.
The fact that a specific remote debug agent choses to use 32 bit
registers is a limitation of that debug agent / kernel. An embedded
target, and I'm pretty sure IRIX 6.5, for instance, don't do that.
Andrew
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-21 16:38 ` Andrew Cagney
@ 2003-05-21 16:58 ` Daniel Jacobowitz
2003-05-21 18:32 ` Kevin Buettner
0 siblings, 1 reply; 46+ messages in thread
From: Daniel Jacobowitz @ 2003-05-21 16:58 UTC (permalink / raw)
To: Andrew Cagney; +Cc: cgd, kevinb, gdb-patches
On Wed, May 21, 2003 at 12:04:35PM -0400, Andrew Cagney wrote:
>
> >>That came out wrong.
> >>
> >>I think a GDB debugging a remote 64 bit MIPS ISA should always expect 64
> >>bit GPRs and 64 bit FPRs when the ISA is 64 bits, regardless of the ABI.
> >>
> >>It is quite legitimate, for instance, for GDB to do something as sick-o
> >>as clearing the FR bit and then resume the thread. The register
> >>save/restore code needs to correctly handle this - be it reject the
> >>operation or ``do the right thing''.
> >
> >
> >But when using rda or gdbserver to debug an o32 application, then for
> >all intents and purposes we are debugging a 32-bit ISA. The kernel
> >will not allow us to change the FR bit. The app will never see 64-bit
> >registers. The 32-bit protocol makes more sense here IMO.
>
> From GDB's view point, the ISA is 64 bit.
>
> The fact that a specific remote debug agent choses to use 32 bit
> registers is a limitation of that debug agent / kernel. An embedded
> target, and I'm pretty sure IRIX 6.5, for instance, don't do that.
No, from GDB's view point in this situation, the target ISA is _NOT_ 64
bit. Nothing 64-bit is available, either to the inferior or to the
debugger. Period.
I would be a little surprised if IRIX didn't work that way too, but I
don't have access to IRIX to poke around.
Certainly straight embedded is different. For those obviously the
64-bit protocol is appropriate.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-21 16:58 ` Daniel Jacobowitz
@ 2003-05-21 18:32 ` Kevin Buettner
2003-05-21 19:15 ` Andrew Cagney
0 siblings, 1 reply; 46+ messages in thread
From: Kevin Buettner @ 2003-05-21 18:32 UTC (permalink / raw)
To: Daniel Jacobowitz, Andrew Cagney; +Cc: cgd, kevinb, gdb-patches
On May 21, 12:58pm, Daniel Jacobowitz wrote:
> > From GDB's view point, the ISA is 64 bit.
> >
> > The fact that a specific remote debug agent choses to use 32 bit
> > registers is a limitation of that debug agent / kernel. An embedded
> > target, and I'm pretty sure IRIX 6.5, for instance, don't do that.
>
> No, from GDB's view point in this situation, the target ISA is _NOT_ 64
> bit. Nothing 64-bit is available, either to the inferior or to the
> debugger. Period.
>
> I would be a little surprised if IRIX didn't work that way too, but I
> don't have access to IRIX to poke around.
I too would be surprised. I should think that SGI would want to
ensure that legacy programs (i.e, those using the o32 ABI) behave the
same when run on 64-bit hardware as they do when run on 32-bit
hardware. One of the implications of this is that illegal
instructions in the 32-bit ISA should continue to be illegal when run
on the 64-bit hardware.
Kevin
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-21 18:32 ` Kevin Buettner
@ 2003-05-21 19:15 ` Andrew Cagney
2003-05-21 19:45 ` Kevin Buettner
2003-05-22 0:32 ` Daniel Jacobowitz
0 siblings, 2 replies; 46+ messages in thread
From: Andrew Cagney @ 2003-05-21 19:15 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Daniel Jacobowitz, cgd, gdb-patches
> On May 21, 12:58pm, Daniel Jacobowitz wrote:
>
>
>> > From GDB's view point, the ISA is 64 bit.
>> >
>> > The fact that a specific remote debug agent choses to use 32 bit
>> > registers is a limitation of that debug agent / kernel. An embedded
>> > target, and I'm pretty sure IRIX 6.5, for instance, don't do that.
>
>>
>> No, from GDB's view point in this situation, the target ISA is _NOT_ 64
>> bit. Nothing 64-bit is available, either to the inferior or to the
>> debugger. Period.
>>
>> I would be a little surprised if IRIX didn't work that way too, but I
>> don't have access to IRIX to poke around.
>
>
> I too would be surprised. I should think that SGI would want to
> ensure that legacy programs (i.e, those using the o32 ABI) behave the
> same when run on 64-bit hardware as they do when run on 32-bit
> hardware. One of the implications of this is that illegal
> instructions in the 32-bit ISA should continue to be illegal when run
> on the 64-bit hardware.
Er, it's the same deal as for SPARC. If GDB is built against the 64 bit
debug interface, it can debug both 32 and 64 bit applications. This is
the debuggers view, not the program being run's view.
Andrew
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-21 19:15 ` Andrew Cagney
@ 2003-05-21 19:45 ` Kevin Buettner
2003-05-22 0:32 ` Daniel Jacobowitz
1 sibling, 0 replies; 46+ messages in thread
From: Kevin Buettner @ 2003-05-21 19:45 UTC (permalink / raw)
To: Andrew Cagney, Kevin Buettner; +Cc: Daniel Jacobowitz, cgd, gdb-patches
On May 21, 3:15pm, Andrew Cagney wrote:
> > On May 21, 12:58pm, Daniel Jacobowitz wrote:
> >
> >> > From GDB's view point, the ISA is 64 bit.
> >> >
> >> > The fact that a specific remote debug agent choses to use 32 bit
> >> > registers is a limitation of that debug agent / kernel. An embedded
> >> > target, and I'm pretty sure IRIX 6.5, for instance, don't do that.
> >
> >>
> >> No, from GDB's view point in this situation, the target ISA is _NOT_ 64
> >> bit. Nothing 64-bit is available, either to the inferior or to the
> >> debugger. Period.
> >>
> >> I would be a little surprised if IRIX didn't work that way too, but I
> >> don't have access to IRIX to poke around.
> >
> >
> > I too would be surprised. I should think that SGI would want to
> > ensure that legacy programs (i.e, those using the o32 ABI) behave the
> > same when run on 64-bit hardware as they do when run on 32-bit
> > hardware. One of the implications of this is that illegal
> > instructions in the 32-bit ISA should continue to be illegal when run
> > on the 64-bit hardware.
>
> Er, it's the same deal as for SPARC. If GDB is built against the 64 bit
> debug interface, it can debug both 32 and 64 bit applications. This is
> the debuggers view, not the program being run's view.
Well, sure. But for such applications, you don't lose anything by
permitting GDB to view it as a 32-bit application only. I.e, there's
nothing that the application is going to do for which there will be a
benefit to have a 64-bit view of it from the outside.
Kevin
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-21 19:15 ` Andrew Cagney
2003-05-21 19:45 ` Kevin Buettner
@ 2003-05-22 0:32 ` Daniel Jacobowitz
2003-05-23 18:39 ` Andrew Cagney
1 sibling, 1 reply; 46+ messages in thread
From: Daniel Jacobowitz @ 2003-05-22 0:32 UTC (permalink / raw)
To: Andrew Cagney; +Cc: Kevin Buettner, cgd, gdb-patches
On Wed, May 21, 2003 at 03:15:00PM -0400, Andrew Cagney wrote:
> >On May 21, 12:58pm, Daniel Jacobowitz wrote:
> >
> >
> >>> From GDB's view point, the ISA is 64 bit.
> >>>
> >>> The fact that a specific remote debug agent choses to use 32 bit
> >>> registers is a limitation of that debug agent / kernel. An embedded
> >>> target, and I'm pretty sure IRIX 6.5, for instance, don't do that.
> >
> >>
> >>No, from GDB's view point in this situation, the target ISA is _NOT_ 64
> >>bit. Nothing 64-bit is available, either to the inferior or to the
> >>debugger. Period.
> >>
> >>I would be a little surprised if IRIX didn't work that way too, but I
> >>don't have access to IRIX to poke around.
> >
> >
> >I too would be surprised. I should think that SGI would want to
> >ensure that legacy programs (i.e, those using the o32 ABI) behave the
> >same when run on 64-bit hardware as they do when run on 32-bit
> >hardware. One of the implications of this is that illegal
> >instructions in the 32-bit ISA should continue to be illegal when run
> >on the 64-bit hardware.
>
> Er, it's the same deal as for SPARC. If GDB is built against the 64 bit
> debug interface, it can debug both 32 and 64 bit applications. This is
> the debuggers view, not the program being run's view.
But the point is that the debugger's view of a 32-bit application on
MIPS is of a 32-bit ISA. That's all that's available. You get 32-bit
registers from the kernel.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-22 0:32 ` Daniel Jacobowitz
@ 2003-05-23 18:39 ` Andrew Cagney
2003-05-23 19:02 ` Daniel Jacobowitz
0 siblings, 1 reply; 46+ messages in thread
From: Andrew Cagney @ 2003-05-23 18:39 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Kevin Buettner, cgd, gdb-patches
>> Er, it's the same deal as for SPARC. If GDB is built against the 64 bit
>> debug interface, it can debug both 32 and 64 bit applications. This is
>> the debuggers view, not the program being run's view.
>
>
> But the point is that the debugger's view of a 32-bit application on
> MIPS is of a 32-bit ISA. That's all that's available. You get 32-bit
> registers from the kernel.
That isn't true. CF the embedded case. The ISA can be 64 bits, but the
ABI 32 bits. This argument is becomming circular.
GDB has to make a choice. Either hack the tdep code so that it tries to
get the user, register, and target ABIs to all line up, or select an
underlying canonical ISA and expect targets to map their register values
onto that. Selecting a definitive 64 bit ISA means that the tdep code
works in all cases - the target is made responsibile for resolving self
inflicted esoteric edge cases.
Note here that the self inflicting esoteric target is remote.c, it is
still tied to the register cache at the hip :-(
Andrew
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-23 18:39 ` Andrew Cagney
@ 2003-05-23 19:02 ` Daniel Jacobowitz
2003-05-23 20:45 ` Andrew Cagney
0 siblings, 1 reply; 46+ messages in thread
From: Daniel Jacobowitz @ 2003-05-23 19:02 UTC (permalink / raw)
To: Andrew Cagney; +Cc: Kevin Buettner, cgd, gdb-patches
On Fri, May 23, 2003 at 02:21:49PM -0400, Andrew Cagney wrote:
>
> >>Er, it's the same deal as for SPARC. If GDB is built against the 64 bit
> >>debug interface, it can debug both 32 and 64 bit applications. This is
> >>the debuggers view, not the program being run's view.
> >
> >
> >But the point is that the debugger's view of a 32-bit application on
> >MIPS is of a 32-bit ISA. That's all that's available. You get 32-bit
> >registers from the kernel.
>
> That isn't true. CF the embedded case. The ISA can be 64 bits, but the
> ABI 32 bits. This argument is becomming circular.
I'm not talking about the embedded case! I never said that we should
always use a 32-bit protocol when debugging a 32-bit ABI. I said that
in this case, using rda or gdbserver on a hosted system, it doesn't
make any sense to use the 64-bit protocol.
> GDB has to make a choice. Either hack the tdep code so that it tries to
> get the user, register, and target ABIs to all line up, or select an
> underlying canonical ISA and expect targets to map their register values
> onto that. Selecting a definitive 64 bit ISA means that the tdep code
> works in all cases - the target is made responsibile for resolving self
> inflicted esoteric edge cases.
Then why have the 32-bit protocol at all, besides compatibility with
existing stubs? Just waste the transfer time for the unused bits all
the time.
> Note here that the self inflicting esoteric target is remote.c, it is
> still tied to the register cache at the hip :-(
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-23 19:02 ` Daniel Jacobowitz
@ 2003-05-23 20:45 ` Andrew Cagney
0 siblings, 0 replies; 46+ messages in thread
From: Andrew Cagney @ 2003-05-23 20:45 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Kevin Buettner, cgd, gdb-patches
> On Fri, May 23, 2003 at 02:21:49PM -0400, Andrew Cagney wrote:
>
>>
>
>> >>Er, it's the same deal as for SPARC. If GDB is built against the 64 bit
>> >>debug interface, it can debug both 32 and 64 bit applications. This is
>> >>the debuggers view, not the program being run's view.
>
>> >
>> >
>> >But the point is that the debugger's view of a 32-bit application on
>> >MIPS is of a 32-bit ISA. That's all that's available. You get 32-bit
>> >registers from the kernel.
>
>>
>> That isn't true. CF the embedded case. The ISA can be 64 bits, but the
>> ABI 32 bits. This argument is becomming circular.
>
>
> I'm not talking about the embedded case! I never said that we should
> always use a 32-bit protocol when debugging a 32-bit ABI. I said that
> in this case, using rda or gdbserver on a hosted system, it doesn't
> make any sense to use the 64-bit protocol.
GDB shouldn't be differentiating. It's a remote.c problem.
>> GDB has to make a choice. Either hack the tdep code so that it tries to
>> get the user, register, and target ABIs to all line up, or select an
>> underlying canonical ISA and expect targets to map their register values
>> onto that. Selecting a definitive 64 bit ISA means that the tdep code
>> works in all cases - the target is made responsibile for resolving self
>> inflicted esoteric edge cases.
>
>
> Then why have the 32-bit protocol at all, besides compatibility with
> existing stubs? Just waste the transfer time for the unused bits all
> the time.
If the self inflicting esoteric remote target and the regcache were no
longer connected at the hip, more efficient register protocols could be
used. Anyway some packing techniques:
- T packets (available now)
- proposed short T register values
- proposed [pP] packet to request additional registers
- proposed ``!'' [for network byte ordered] register values
- use of run-length encoding (available now?)
- use of -1 to encode 0xffffffffffffffff (available now?)
>> Note here that the self inflicting esoteric target is remote.c, it is
>> still tied to the register cache at the hip :-(
Andrew
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-21 15:40 ` Andrew Cagney
@ 2003-06-15 1:44 ` Andrew Cagney
2003-06-16 18:06 ` cgd
0 siblings, 1 reply; 46+ messages in thread
From: Andrew Cagney @ 2003-06-15 1:44 UTC (permalink / raw)
To: cgd; +Cc: Kevin Buettner, gdb-patches
[-- Attachment #1: Type: text/plain, Size: 7 bytes --]
Chris?
[-- Attachment #2: mailbox-message://ac131313@movemail/fsf/gdb/patches#8430822 --]
[-- Type: message/rfc822, Size: 4928 bytes --]
From: Andrew Cagney <ac131313@redhat.com>
To: cgd@broadcom.com
Cc: Kevin Buettner <kevinb@redhat.com>, gdb-patches@sources.redhat.com
Subject: Re: [WIP/RFC] MIPS registers overhaul
Date: Wed, 21 May 2003 11:40:18 -0400
Message-ID: <3ECB9DE2.1020906@redhat.com>
> At Tue, 20 May 2003 16:23:34 -0400, Andrew Cagney wrote:
>
>> When a 64 bit kernel goes to save/resume an o32 process, how does it do
>> it? Does it have a choice?
>
>
> it has limited choice.
>
>
>
>> For instance, do a 64 bit FP restore then clear the FR bit; the reverse;
>> some other variant; ...?
>
>
> So, if the process is running with FR=0, then the save/restore should
> ("must" i believe) be done with FR=0.
>
> When FR=0, there are two options as to how to do it:
>
> for (i = 0; i < 32; i++)
> move/store word from c1 reg $i (i.e., dmfc1/sdc1)
>
> OR:
>
> for (i = 0; i < 32; i += 2)
> move/store dword from c1 reg $i (i.e., dmfc1/sdc1)
That isn't quite the detail I was looking for. Does the code need to
look like:
save::
save FSR
if (FSR & FR)
save 32x32 FP
else
save 32x64 FP
restore::
restore FSR
if (FSR & FR)
restore 32x32 FP
else
restore 32x64 FP
that is, the FSR[FR] bit (wonder if I've got the names right) needs to
set/clear the FR bit before it even starts to consider saving/restoring
the other registers. The reverse operation:
save::
save FSR
make FP registers 64 bit
save 32x64 FP
restore::
// assume FSR[FR] set to 64 bit mode
restore 32x64 FP
restore FSR
operation not being valid.
Andrew
> (move to / load for the state restore, of course.)
>
> (of course, these will typically be written in assembly code, and
> "fully unrolled" -- the pseudo-C-code is to demonstrate the concept
> only.)
>
> either one is valid, though all implementations that I know of choose
> the latter because it's fewer instructions and almost certainly more
> efficient.
>
>
> the linux kernel presents that to o32 userland (o32 ptrace syscall) as
> an array of 32 32-bit values, but IIRC it's stored internally as (8
> byte reg, 8 byte pad) * 16.
>
>
>
> cgd
>
>
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-05-20 20:32 ` cgd
2003-05-21 15:40 ` Andrew Cagney
@ 2003-06-15 17:23 ` Andrew Cagney
2003-06-16 20:06 ` cgd
1 sibling, 1 reply; 46+ messages in thread
From: Andrew Cagney @ 2003-06-15 17:23 UTC (permalink / raw)
To: cgd, Kevin Buettner; +Cc: gdb-patches
>> For instance, do a 64 bit FP restore then clear the FR bit; the reverse;
>> some other variant; ...?
>
>
> So, if the process is running with FR=0, then the save/restore should
> ("must" i believe) be done with FR=0.
>
> When FR=0, there are two options as to how to do it:
>
> for (i = 0; i < 32; i++)
> move/store word from c1 reg $i (i.e., dmfc1/sdc1)
mfc1/sc1
> OR:
>
> for (i = 0; i < 32; i += 2)
> move/store dword from c1 reg $i (i.e., dmfc1/sdc1)
OK, I'm going to go out on a limb here. I don't think the two are
equivalent, and I think the second is wrong. For big-endian, the second
would store fp[n+0] ||| fp[n+1] backwards.
When extracting a double from a MIPS register pair, GDB does the rough
equivalent of:
if (big-endian && type == double)
memcpy (dest + 0, &fp[regnum + 1], 4);
memcpy (dest + 4, &fp[regnum + 0], 4);
else if (little-endian && type == double)
memcpy (dest + 0, &fp[regnum + 0], 4);
memcpy (dest + 4, &fp[regnum + 1], 4);
(See register_to_type. The code dates back to ~92 and was added to fix
IRIX double value display problems.) The effect is to always get the
least significant part of a double value from fp[n+0], and the most
significant from fp[n+1].
Given MIPS xor endian sillyness, it's hard to see this is happening,
however looking at (MIPS IV ref 3.2) DMFC1, given a 32 bit FGR, it does:
GPR[rt] = FGR[fs+1] ||| FGR[fs+0]
A double word store of that GPR would then order the value as:
0: FGR[fs+0]
1: FGR[fs+1]
little endian, and
0: FGR[fs+1]
1: FGR[fs+0]
big endian.
If you stare at LDC1 long enough, remembering that LoadMemory contains
the horrible XOR magic, you'll realise that it has the same effect.
Anyway, this, I believe, means that any implementation of:
union {
float flt;
double dbl;
int32 i32;
int64 i64;
} $fp0
is going to need, for BE, a big-byte little-word DOUBLE, and a similar
INT64. Otherwize, $f0.int32 would modify the wrong part of the double
register. Alternatively, some of those union values could be given
magic offsets. Looking at kevin's patch:
+ t = init_composite_type ("__gdb_mips_type_float_double_register_big",
+ TYPE_CODE_UNION);
+ append_composite_type_field (t, "i", builtin_type_uint64);
+ append_composite_type_field (t, "f", builtin_type_ieee_single_big);
+ f = &(TYPE_FIELDS (t))[TYPE_NFIELDS (t) - 1];
+ FIELD_BITPOS (f[0]) = 32;
+ append_composite_type_field (t, "d", builtin_type_ieee_double_big);
+
+ TYPE_NAME (t) = "mips_type_float_double_register_big";
It appears to have taken the second option.
Andrew
> (move to / load for the state restore, of course.)
>
> (of course, these will typically be written in assembly code, and
> "fully unrolled" -- the pseudo-C-code is to demonstrate the concept
> only.)
>
> either one is valid, though all implementations that I know of choose
> the latter because it's fewer instructions and almost certainly more
> efficient.
>
>
> the linux kernel presents that to o32 userland (o32 ptrace syscall) as
> an array of 32 32-bit values, but IIRC it's stored internally as (8
> byte reg, 8 byte pad) * 16.
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-06-15 1:44 ` Andrew Cagney
@ 2003-06-16 18:06 ` cgd
2003-06-16 18:47 ` Andrew Cagney
0 siblings, 1 reply; 46+ messages in thread
From: cgd @ 2003-06-16 18:06 UTC (permalink / raw)
To: Andrew Cagney; +Cc: Kevin Buettner, gdb-patches
At Sat, 14 Jun 2003 21:36:04 -0400, Andrew Cagney wrote:
> Chris?
Sorry, I must have missed that msg... 8-)
> That isn't quite the detail I was looking for. Does the code need to
> look like:
>
> save::
> save FSR
> if (FSR & FR)
*** when FR == 1, it's 32 64-bit registers. so, invert.
> save 32x32 FP
*** or, save 16 (even) 64-bit FP registers, if MIPS2 or later.
*** in fact, on MIPS2 and later, better to do that, since it'll be
*** more efficient (fewer instructions).
> else
> save 32x64 FP
>
> restore::
> restore FSR
> if (FSR & FR)
> restore 32x32 FP
> else
> restore 32x64 FP
>
> that is, the FSR[FR] bit (wonder if I've got the names right) needs to
> set/clear the FR bit before it even starts to consider saving/restoring
> the other registers.
It's Status:FR (or, SR:FR, but i prefer to call the regs by their
proper names 8-). (also, "or, use notation of your choice." 8-)
(it's in the normal CP0 status register, not in any of the FPU control
registers. all of the latter are user-accessable, but Status:FR is
not.)
> The reverse operation:
>
> save::
> save FSR
> make FP registers 64 bit
> save 32x64 FP
>
> restore::
> // assume FSR[FR] set to 64 bit mode
> restore 32x64 FP
> restore FSR
>
> operation not being valid.
So, I looked at the specifications, and I don't couldn't find any
place where this is defined by the current architecture to be
UNPREDICTABLE, but i may have missed it.
I would expect -- but haven't checked -- that this would work as well.
Looking at the diagrams in the MIPS32 and MIPS64 specs which try to
explain opration behaviour w/ the various FR modes, I think i'd
*expect* it to work.
Based on the diagrams in the manuals, I'd *expect* that if you do
this, the even registers would contain all of the data used in FR=0
mode, and the odd registers would contain... whatever they were
initialized with when FR was set to 0 initially.
Personally, I wouldn't do this. 8-)
Note also that some processors do have ... interesting hazards when
changing Status:FR modes, too. If one can keep the number of FR mode
changes to a minimum one can also reduce the number of
hazard-avoidance sequences needed. In the former example, you do one
Status:FR set per save/restore. In the latter, you do two.
cgd
--
Chris Demetriou Broadcom Corporation
Principal Design Engineer Broadband Processor Business Unit
Any opinions expressed in this message are mine, not necessarily Broadcom's.
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-06-16 18:06 ` cgd
@ 2003-06-16 18:47 ` Andrew Cagney
0 siblings, 0 replies; 46+ messages in thread
From: Andrew Cagney @ 2003-06-16 18:47 UTC (permalink / raw)
To: cgd; +Cc: Kevin Buettner, gdb-patches
> At Sat, 14 Jun 2003 21:36:04 -0400, Andrew Cagney wrote:
>
>> Chris?
>
>
> Sorry, I must have missed that msg... 8-)
>
>
>
>> That isn't quite the detail I was looking for. Does the code need to
>> look like:
>>
>> save::
>> save FSR
>> if (FSR & FR)
>
> *** when FR == 1, it's 32 64-bit registers. so, invert.
>
>> save 32x32 FP
>
> *** or, save 16 (even) 64-bit FP registers, if MIPS2 or later.
> *** in fact, on MIPS2 and later, better to do that, since it'll be
> *** more efficient (fewer instructions).
But see my other post. Using a double store gives different behavior to
two single stores. I guess the kernel can do a double store, only then
swapping the registers before supplying them to gdb.
Andrew
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-06-15 17:23 ` Andrew Cagney
@ 2003-06-16 20:06 ` cgd
2003-06-16 20:41 ` Andrew Cagney
0 siblings, 1 reply; 46+ messages in thread
From: cgd @ 2003-06-16 20:06 UTC (permalink / raw)
To: Andrew Cagney; +Cc: Kevin Buettner, gdb-patches
It's unfair to make me think really hard after being gone for almost a
week. I've had to resort to experimental analysis. 8-)
It would be good, BTW, to reference against the MIPS32 or MIPS64
specs; I dunno that everybody in the world has a MIPS IV spec, and
certainly I might but if i do it's not as handy.
At Sun, 15 Jun 2003 13:23:21 -0400, Andrew Cagney wrote:
> >> For instance, do a 64 bit FP restore then clear the FR bit; the
> >> reverse; some other variant; ...?
> > So, if the process is running with FR=0, then the save/restore should
> > ("must" i believe) be done with FR=0.
> > When FR=0, there are two options as to how to do it:
> > for (i = 0; i < 32; i++)
> > move/store word from c1 reg $i (i.e., dmfc1/sdc1)
>
> mfc1/sc1
yah.
> > OR:
> > for (i = 0; i < 32; i += 2)
> > move/store dword from c1 reg $i (i.e., dmfc1/sdc1)
>
> OK, I'm going to go out on a limb here. I don't think the two are
> equivalent, and I think the second is wrong. For big-endian, the
> second would store fp[n+0] ||| fp[n+1] backwards.
No, the two are not equivalent, in terms of the memory layout that
results on big endian systems. (On little-endian systems, AFAICT they
end up producing the same results.)
However, neither is more correct w.r.t. what's allowed by the MIPS
architecture; both will work with MIPS2 and later hardware. Doing the
stores as dwords is clearly more efficient, though.
> When extracting a double from a MIPS register pair, GDB does the rough
> equivalent of:
>
> [...]
>
> (See register_to_type. The code dates back to ~92 and was added to
> fix IRIX double value display problems.) The effect is to always get
> the least significant part of a double value from fp[n+0], and the
> most significant from fp[n+1].
Err, I'm not sure what code you reference. I couldn't find
"register_to_type" (case insensitively), anywhere in the GDB source.
I do note that the code in mips-tdep.c:
static void
mips_read_fp_register_single (struct frame_info *frame, int regno,
char *rare_buffer)
static void
mips_read_fp_register_double (struct frame_info *frame, int regno,
char *rare_buffer)
but i'm not sure whether your pseudo-code above is meant to convey the
operation of the latter, and, if so for 8-byte FPRs (with the mips2
compat thing), or 4 byte FPRs... (8 byte FPRs with mips2 compat looks
... scary. 8-)
> Given MIPS xor endian sillyness,
I'm not quite sure which silliness you mean.
The "ReverseEndian" xoring (in the pseudo-code) happens only if
Status:RE is set. I'll admit that the 'bytesel' logic in the sw/swc1
ops takes a while to understand. 8-)
Normally (when RE is not set) it behaves in (IMO) a sane enough way...
> Anyway, this, I believe, means that any implementation of:
>
> union {
> float flt;
> double dbl;
> int32 i32;
> int64 i64;
> } $fp0
>
> is going to need, for BE, a big-byte little-word DOUBLE, and a similar
> INT64. Otherwize, $f0.int32 would modify the wrong part of the double
> register. Alternatively, some of those union values could be given
> magic offsets. Looking at kevin's patch:
Right. I think the "assume 4 bytes of pad before the 4-byte item" is
the right way to look at it.
And then to follow on from that:
* if 32-bit FPU (32-bit MIPS or 64-bit MIPS with FR == 0), assume you
have 16 of them, or
* if 64-bit FPU, you have 32.
(at least, that's the way it should work for "normal" FPU usage. For
single-float, where $f0 and $f1 contain independent singles, it's
another story.)
Re: your other message, re: the kernel shifting them around:
I *think* that the linux kernel does shift things around as
appropriate, at least for the r4k-and-later chips. (TBH, I'm not sure
that it's correct for the r2k/r3k.)
It's been so long that i forgot what the issue at the root of this
disucssion was. Could you remind me? 8-)
cgd
--
Chris Demetriou Broadcom Corporation
Principal Design Engineer Broadband Processor Business Unit
Any opinions expressed in this message are mine, not necessarily Broadcom's.
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-06-16 20:06 ` cgd
@ 2003-06-16 20:41 ` Andrew Cagney
[not found] ` <mailpost.1055796186.4097@news-sj1-1>
0 siblings, 1 reply; 46+ messages in thread
From: Andrew Cagney @ 2003-06-16 20:41 UTC (permalink / raw)
To: cgd; +Cc: Kevin Buettner, gdb-patches
>> OK, I'm going to go out on a limb here. I don't think the two are
>> equivalent, and I think the second is wrong. For big-endian, the
>> second would store fp[n+0] ||| fp[n+1] backwards.
>
>
> No, the two are not equivalent, in terms of the memory layout that
> results on big endian systems. (On little-endian systems, AFAICT they
> end up producing the same results.)
>
> However, neither is more correct w.r.t. what's allowed by the MIPS
> architecture; both will work with MIPS2 and later hardware. Doing the
> stores as dwords is clearly more efficient, though.
The IRIX kernel exports an interface that makes it appear as though two
single stores were used. To GDB, that interface is all that matters :-)
> Err, I'm not sure what code you reference. I couldn't find
> "register_to_type" (case insensitively), anywhere in the GDB source.
Sorry, it was register_to_type. It's been replaced with register_to_value.
> is going to need, for BE, a big-byte little-word DOUBLE, and a similar
>> INT64. Otherwize, $f0.int32 would modify the wrong part of the double
>> register. Alternatively, some of those union values could be given
>> magic offsets. Looking at kevin's patch:
>
>
> Right. I think the "assume 4 bytes of pad before the 4-byte item" is
> the right way to look at it.
The kernel, when it presents the value to GDB, doesn't do that. It puts
the even register in the low address. If possible the register's type
should reflect the underlying format - big-byte, little-word.
> And then to follow on from that:
>
> * if 32-bit FPU (32-bit MIPS or 64-bit MIPS with FR == 0), assume you
> have 16 of them, or
Careful. If the ABI is o32, and FR == 0/..., then there should be only
16 floating point registers in use. The original MIPS 1, and r5900 ABIs
would both allow use of all 32 32 bit floating point registers.
> * if 64-bit FPU, you have 32.
>
> (at least, that's the way it should work for "normal" FPU usage. For
> single-float, where $f0 and $f1 contain independent singles, it's
> another story.)
Yes.
Andrew
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
[not found] ` <mailpost.1055796186.4097@news-sj1-1>
@ 2003-06-17 5:04 ` cgd
2003-06-17 14:27 ` Andrew Cagney
0 siblings, 1 reply; 46+ messages in thread
From: cgd @ 2003-06-17 5:04 UTC (permalink / raw)
To: ac131313; +Cc: Kevin Buettner, gdb-patches
At Mon, 16 Jun 2003 20:43:06 +0000 (UTC), "Andrew Cagney" wrote:
> > And then to follow on from that:
> > * if 32-bit FPU (32-bit MIPS or 64-bit MIPS with FR == 0), assume you
> > have 16 of them, or
>
> Careful. If the ABI is o32, and FR == 0/..., then there should be
> only 16 floating point registers in use. The original MIPS 1, and
> r5900 ABIs would both allow use of all 32 32 bit floating point
> registers.
I don't know that that is correct, at least about the "original MIPS
1" behaviour.
I have here a copy of Kane's "MIPS RISC Architecture" which describes
the r2k/r3k (and FPA). (Mmm, books > 10 yrs old. 8-)
For all of the FP operate instructions:
ADD.fmt SUB.fmt MUL.fmt DIV.fmt ABS.fmt MOV.fmt NEG.fmt
CVT.S.fmt CVT.D.fmt C.cond.fmt
(i.e., all of the operate instructions except CVT.W.fmt), there are
words like the following in the instruction description:
On the FPA, this operation is valid only for double- or
single-precision floating-point formats. This operation is
not defined if bit 0 of any register specification is set, as
the register numbers specify and even-odd pair of adjacent
coprocessor general registers (FGR).
There are slightly variations in wording in the first sentence (extra
words for the CVT.[SD].fmt ops), and for the CVT.[SD].fmt ops single
fixed-point format is allowed and the type of the op isn't allowed
(i.e., no double for CVT.D.fmt).
Note that CVT.W.fmt uses the wording for the second sentence:
For double-precision format, this operation is not defined
[rest of sentence as above].
Note that the Kane/Heinrich version that includes the r6k and r4k
makes a complete mess of the issue, using different wording that *does
not* AFAIK agree with the above. Of course, it omits a bunch of
things and gets a bunch of things wrong, so more lossage isn't
surprising to me. 8-)
cgd
--
Chris Demetriou Broadcom Corporation
Principal Design Engineer Broadband Processor Business Unit
Any opinions expressed in this message are mine, not necessarily Broadcom's.
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
2003-06-17 5:04 ` cgd
@ 2003-06-17 14:27 ` Andrew Cagney
[not found] ` <mailpost.1055860052.3406@news-sj1-1>
0 siblings, 1 reply; 46+ messages in thread
From: Andrew Cagney @ 2003-06-17 14:27 UTC (permalink / raw)
To: cgd; +Cc: Kevin Buettner, gdb-patches
> Careful. If the ABI is o32, and FR == 0/..., then there should be
>> only 16 floating point registers in use. The original MIPS 1, and
>> r5900 ABIs would both allow use of all 32 32 bit floating point
>> registers.
>
>
> I don't know that that is correct, at least about the "original MIPS
> 1" behaviour.
Sigh, yes: B 3.3 Formatted Operand Layout of [3.2]:
FPU instructions that operate on formatted operand values specify the
floating-point register (FPR) that holds a value. An FPR is not
necessarily the same as a CP1 general register because an FPR is 64 bits
wide; if this is wider than the CP1 general registers, an aligned set of
adjacent CP1 general registers is used as the FPR. The 32-bit register
model provides 16 FPRs specified by the even CP1 general register
numbers. The 64-bit register model provides 32 FPRs, one per CP1 general
register. Operands that are only 32 bits wide (W and S formats), use
only half the space in an FPR. The FPR organization and the way that
operand data is stored in them is shown in the following figures. A
summary of the data transfer instructions can be found in section B 6.1
on page B-19.
The key bit being that the terminology differentaties between a 32 bit
CP1 register and a 64 bit FPR.
This also suggests a better way of representing the registers to the user:
MIPS I:
$cp0, $cp1, ...: 32/64 bit raw co-processor registers
MIPS I:
$fp0, $fp2, ...: 64 bit co-processor registers
note that these are little word ordered
and contain 32 and 64 bit float values
(This was suggested to me in a second hand
off line discussion :-()
MIPS III:
$fp0, $fp1, ...: 64 bit floating point registers
Andrew
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [WIP/RFC] MIPS registers overhaul
[not found] ` <mailpost.1055860052.3406@news-sj1-1>
@ 2003-06-17 16:27 ` cgd
0 siblings, 0 replies; 46+ messages in thread
From: cgd @ 2003-06-17 16:27 UTC (permalink / raw)
To: ac131313; +Cc: Kevin Buettner, gdb-patches
At Tue, 17 Jun 2003 14:27:32 +0000 (UTC), "Andrew Cagney" wrote:
> The key bit being that the terminology differentaties between a 32 bit
> CP1 register and a 64 bit FPR.
^^^^^^^^^^^^
a.k.a. "FGR"
> This also suggests a better way of representing the registers to the user:
>
> MIPS I:
> $cp0, $cp1, ...: 32/64 bit raw co-processor registers
I would strongly recommend "$fgrN" since:
* that follows the manual more closely (see my previous cites;
unfortunately i can't quote the C&V's right now since my Kane is at
home 8-),
* "cpN" (a.k.a. "copN") already have fairly-well understood meanings
in MIPS-wordl which aren't this, and assmuing that one might want to
provide useful names for, oh, say, the cp2 registers, and that might
confusing very quickly.
Of course, re: the latter point of the second bullet, it looks like
gcc already believes those registers to be named "$c2rN", so at least
little bit's a red herring. 8-)
chris
^ permalink raw reply [flat|nested] 46+ messages in thread
end of thread, other threads:[~2003-06-17 16:27 UTC | newest]
Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-05-10 0:25 [WIP/RFC] MIPS registers overhaul Kevin Buettner
2003-05-10 20:30 ` Andrew Cagney
2003-05-10 20:40 ` Daniel Jacobowitz
2003-05-14 22:00 ` Kevin Buettner
[not found] ` <mailpost.1052949911.28802@news-sj1-1>
2003-05-14 23:35 ` cgd
2003-05-15 0:07 ` Kevin Buettner
2003-05-15 0:15 ` Daniel Jacobowitz
2003-05-15 22:01 ` Kevin Buettner
2003-05-16 3:24 ` Andrew Cagney
2003-05-16 4:00 ` Andrew Cagney
2003-05-16 17:20 ` Kevin Buettner
[not found] ` <mailpost.1053057614.17325@news-sj1-1>
2003-05-16 22:25 ` cgd
[not found] ` <mailpost.1053123913.16634@news-sj1-1>
2003-05-16 22:50 ` cgd
2003-05-16 23:05 ` Kevin Buettner
[not found] ` <mailpost.1053126410.17856@news-sj1-1>
2003-05-16 23:24 ` cgd
2003-05-17 0:41 ` Kevin Buettner
2003-05-17 20:59 ` Daniel Jacobowitz
2003-05-20 20:18 ` Always remote: " Andrew Cagney
2003-05-20 20:26 ` Daniel Jacobowitz
[not found] ` <mailpost.1053132070.20348@news-sj1-1>
2003-05-20 20:37 ` cgd
2003-05-20 20:51 ` Kevin Buettner
2003-05-20 20:52 ` Andrew Cagney
2003-05-20 21:57 ` cgd
2003-05-21 15:34 ` Andrew Cagney
2003-05-21 15:41 ` Daniel Jacobowitz
2003-05-21 16:38 ` Andrew Cagney
2003-05-21 16:58 ` Daniel Jacobowitz
2003-05-21 18:32 ` Kevin Buettner
2003-05-21 19:15 ` Andrew Cagney
2003-05-21 19:45 ` Kevin Buettner
2003-05-22 0:32 ` Daniel Jacobowitz
2003-05-23 18:39 ` Andrew Cagney
2003-05-23 19:02 ` Daniel Jacobowitz
2003-05-23 20:45 ` Andrew Cagney
2003-05-20 20:25 ` Andrew Cagney
2003-05-20 20:32 ` cgd
2003-05-21 15:40 ` Andrew Cagney
2003-06-15 1:44 ` Andrew Cagney
2003-06-16 18:06 ` cgd
2003-06-16 18:47 ` Andrew Cagney
2003-06-15 17:23 ` Andrew Cagney
2003-06-16 20:06 ` cgd
2003-06-16 20:41 ` Andrew Cagney
[not found] ` <mailpost.1055796186.4097@news-sj1-1>
2003-06-17 5:04 ` cgd
2003-06-17 14:27 ` Andrew Cagney
[not found] ` <mailpost.1055860052.3406@news-sj1-1>
2003-06-17 16:27 ` cgd
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox