diff options
-rw-r--r-- | gdb/ChangeLog | 21 | ||||
-rw-r--r-- | gdb/Makefile.in | 2 | ||||
-rw-r--r-- | gdb/NEWS | 4 | ||||
-rw-r--r-- | gdb/doc/ChangeLog | 4 | ||||
-rw-r--r-- | gdb/doc/gdb.texinfo | 17 | ||||
-rw-r--r-- | gdb/features/mips-cp0.xml | 13 | ||||
-rw-r--r-- | gdb/features/mips-cpu.xml | 46 | ||||
-rw-r--r-- | gdb/features/mips-fpu.xml | 45 | ||||
-rw-r--r-- | gdb/features/mips64-cp0.xml | 13 | ||||
-rw-r--r-- | gdb/features/mips64-cpu.xml | 46 | ||||
-rw-r--r-- | gdb/features/mips64-fpu.xml | 45 | ||||
-rw-r--r-- | gdb/mips-tdep.c | 298 | ||||
-rw-r--r-- | gdb/target-descriptions.c | 51 | ||||
-rw-r--r-- | gdb/target-descriptions.h | 12 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/testsuite/gdb.xml/tdesc-regs.exp | 32 |
16 files changed, 627 insertions, 27 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 22cab68..fe09eb5 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,24 @@ +2007-06-13 Daniel Jacobowitz <dan@codesourcery.com> + + * Makefile.in (mips-tdep.o): Update. + * mips-tdep.c (struct register_alias, mips_o32_aliases) + (mips_n32_n64_aliases, mips_register_aliases): New. + (mips_register_name): Call tdesc_register_name. + (mips_tdesc_register_reggroup_p): New. + (mips_pseudo_register_type, value_of_mips_user_reg): New. + (mips_gdbarch_init): Add target-described register support. + Register aliases for register names. + * target-descriptions.c (tdesc_register_name): Make global. + (tdesc_register_in_reggroup_p): New function, broken out from + tdesc_register_reggroup_p. + (tdesc_register_reggroup_p): Use it. + * target-descriptions.h (tdesc_register_name) + (tdesc_register_in_reggroup_p): New prototypes. + * NEWS: Correct formatting. Mention MIPS register support. + * features/mips-cp0.xml, features/mips-fpu.xml, + features/mips64-cp0.xml, gdb/features/mips64-fpu.xml, mips-cpu.xml, + features/mips64-cpu.xml: New files. + 2007-06-13 Markus Deuling <deuling@de.ibm.com> * gdbarch.sh (TARGET_ADDR_BIT): Replace by gdbarch_addr_bit. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 4704cf8..9b786f2 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -2361,7 +2361,7 @@ mips-tdep.o: mips-tdep.c $(defs_h) $(gdb_string_h) $(gdb_assert_h) \ $(elf_bfd_h) $(symcat_h) $(sim_regno_h) $(dis_asm_h) \ $(frame_unwind_h) $(frame_base_h) $(trad_frame_h) $(infcall_h) \ $(floatformat_h) $(remote_h) $(target_descriptions_h) \ - $(dwarf2_frame_h) + $(dwarf2_frame_h) $(user_regs_h) memory-map.o: memory-map.c $(defs_h) $(memory_map_h) $(xml_support_h) \ $(gdb_assert_h) $(exceptions_h) $(gdb_string_h) mn10300-linux-tdep.o: mn10300-linux-tdep.c $(defs_h) $(gdbcore_h) \ @@ -20,11 +20,11 @@ target's overall architecture. GDB can read a description from a local file or over the remote serial protocol. * Arrays of explicitly SIGNED or UNSIGNED CHARs are now printed as arrays - of numbers. +of numbers. * Target descriptions can now describe target-specific registers, for architectures which have implemented the support (currently -only ARM). +only ARM and MIPS). * GDB and the GDB remote stub, gdbserver, now support the XScale iWMMXt coprocessor. diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 7c1850d..20b2768 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2007-06-13 Daniel Jacobowitz <dan@codesourcery.com> + + * gdb.texinfo (MIPS Features): New subsection. + 2007-06-12 Ulrich Weigand <uweigand@de.ibm.com> Markus Deuling <deuling@de.ibm.com> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 5a3b0a9..937106c 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -25767,6 +25767,23 @@ it should contain at least registers @samp{wR0} through @samp{wR15} and @samp{wCGR0} through @samp{wCGR3}. The @samp{wCID}, @samp{wCon}, @samp{wCSSF}, and @samp{wCASF} registers are optional. +@subsection MIPS Features +@cindex target descriptions, MIPS features + +The @samp{org.gnu.gdb.mips.cpu} feature is required for MIPS targets. +It should contain registers @samp{r0} through @samp{r31}, @samp{lo}, +@samp{hi}, and @samp{pc}. They may be 32-bit or 64-bit depending +on the target. + +The @samp{org.gnu.gdb.mips.cp0} feature is also required. It should +contain at least the @samp{status}, @samp{badvaddr}, and @samp{cause} +registers. They may be 32-bit or 64-bit depending on the target. + +The @samp{org.gnu.gdb.mips.fpu} feature is currently required, though +it may be optional in a future version of @value{GDBN}. It should +contain registers @samp{f0} through @samp{f31}, @samp{fcsr}, and +@samp{fir}. They may be 32-bit or 64-bit depending on the target. + @include gpl.texi @raisesections diff --git a/gdb/features/mips-cp0.xml b/gdb/features/mips-cp0.xml new file mode 100644 index 0000000..67c3250 --- /dev/null +++ b/gdb/features/mips-cp0.xml @@ -0,0 +1,13 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2007 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.mips.cp0"> + <reg name="status" bitsize="32" regnum="32"/> + <reg name="badvaddr" bitsize="32" regnum="35"/> + <reg name="cause" bitsize="32" regnum="36"/> +</feature> diff --git a/gdb/features/mips-cpu.xml b/gdb/features/mips-cpu.xml new file mode 100644 index 0000000..ea285dd --- /dev/null +++ b/gdb/features/mips-cpu.xml @@ -0,0 +1,46 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2007 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.mips.cpu"> + <reg name="r0" bitsize="32"/> + <reg name="r1" bitsize="32"/> + <reg name="r2" bitsize="32"/> + <reg name="r3" bitsize="32"/> + <reg name="r4" bitsize="32"/> + <reg name="r5" bitsize="32"/> + <reg name="r6" bitsize="32"/> + <reg name="r7" bitsize="32"/> + <reg name="r8" bitsize="32"/> + <reg name="r9" bitsize="32"/> + <reg name="r10" bitsize="32"/> + <reg name="r11" bitsize="32"/> + <reg name="r12" bitsize="32"/> + <reg name="r13" bitsize="32"/> + <reg name="r14" bitsize="32"/> + <reg name="r15" bitsize="32"/> + <reg name="r16" bitsize="32"/> + <reg name="r17" bitsize="32"/> + <reg name="r18" bitsize="32"/> + <reg name="r19" bitsize="32"/> + <reg name="r20" bitsize="32"/> + <reg name="r21" bitsize="32"/> + <reg name="r22" bitsize="32"/> + <reg name="r23" bitsize="32"/> + <reg name="r24" bitsize="32"/> + <reg name="r25" bitsize="32"/> + <reg name="r26" bitsize="32"/> + <reg name="r27" bitsize="32"/> + <reg name="r28" bitsize="32"/> + <reg name="r29" bitsize="32"/> + <reg name="r30" bitsize="32"/> + <reg name="r31" bitsize="32"/> + + <reg name="lo" bitsize="32" regnum="33"/> + <reg name="hi" bitsize="32" regnum="34"/> + <reg name="pc" bitsize="32" regnum="37"/> +</feature> diff --git a/gdb/features/mips-fpu.xml b/gdb/features/mips-fpu.xml new file mode 100644 index 0000000..6fb5452 --- /dev/null +++ b/gdb/features/mips-fpu.xml @@ -0,0 +1,45 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2007 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.mips.fpu"> + <reg name="f0" bitsize="32" type="ieee_single"/> + <reg name="f1" bitsize="32" type="ieee_single"/> + <reg name="f2" bitsize="32" type="ieee_single"/> + <reg name="f3" bitsize="32" type="ieee_single"/> + <reg name="f4" bitsize="32" type="ieee_single"/> + <reg name="f5" bitsize="32" type="ieee_single"/> + <reg name="f6" bitsize="32" type="ieee_single"/> + <reg name="f7" bitsize="32" type="ieee_single"/> + <reg name="f8" bitsize="32" type="ieee_single"/> + <reg name="f9" bitsize="32" type="ieee_single"/> + <reg name="f10" bitsize="32" type="ieee_single"/> + <reg name="f11" bitsize="32" type="ieee_single"/> + <reg name="f12" bitsize="32" type="ieee_single"/> + <reg name="f13" bitsize="32" type="ieee_single"/> + <reg name="f14" bitsize="32" type="ieee_single"/> + <reg name="f15" bitsize="32" type="ieee_single"/> + <reg name="f16" bitsize="32" type="ieee_single"/> + <reg name="f17" bitsize="32" type="ieee_single"/> + <reg name="f18" bitsize="32" type="ieee_single"/> + <reg name="f19" bitsize="32" type="ieee_single"/> + <reg name="f20" bitsize="32" type="ieee_single"/> + <reg name="f21" bitsize="32" type="ieee_single"/> + <reg name="f22" bitsize="32" type="ieee_single"/> + <reg name="f23" bitsize="32" type="ieee_single"/> + <reg name="f24" bitsize="32" type="ieee_single"/> + <reg name="f25" bitsize="32" type="ieee_single"/> + <reg name="f26" bitsize="32" type="ieee_single"/> + <reg name="f27" bitsize="32" type="ieee_single"/> + <reg name="f28" bitsize="32" type="ieee_single"/> + <reg name="f29" bitsize="32" type="ieee_single"/> + <reg name="f30" bitsize="32" type="ieee_single"/> + <reg name="f31" bitsize="32" type="ieee_single"/> + + <reg name="fcsr" bitsize="32" group="float"/> + <reg name="fir" bitsize="32" group="float"/> +</feature> diff --git a/gdb/features/mips64-cp0.xml b/gdb/features/mips64-cp0.xml new file mode 100644 index 0000000..ba75c9d --- /dev/null +++ b/gdb/features/mips64-cp0.xml @@ -0,0 +1,13 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2007 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.mips.cp0"> + <reg name="status" bitsize="64" regnum="32"/> + <reg name="badvaddr" bitsize="64" regnum="35"/> + <reg name="cause" bitsize="64" regnum="36"/> +</feature> diff --git a/gdb/features/mips64-cpu.xml b/gdb/features/mips64-cpu.xml new file mode 100644 index 0000000..13e6471 --- /dev/null +++ b/gdb/features/mips64-cpu.xml @@ -0,0 +1,46 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2007 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.mips.cpu"> + <reg name="r0" bitsize="64"/> + <reg name="r1" bitsize="64"/> + <reg name="r2" bitsize="64"/> + <reg name="r3" bitsize="64"/> + <reg name="r4" bitsize="64"/> + <reg name="r5" bitsize="64"/> + <reg name="r6" bitsize="64"/> + <reg name="r7" bitsize="64"/> + <reg name="r8" bitsize="64"/> + <reg name="r9" bitsize="64"/> + <reg name="r10" bitsize="64"/> + <reg name="r11" bitsize="64"/> + <reg name="r12" bitsize="64"/> + <reg name="r13" bitsize="64"/> + <reg name="r14" bitsize="64"/> + <reg name="r15" bitsize="64"/> + <reg name="r16" bitsize="64"/> + <reg name="r17" bitsize="64"/> + <reg name="r18" bitsize="64"/> + <reg name="r19" bitsize="64"/> + <reg name="r20" bitsize="64"/> + <reg name="r21" bitsize="64"/> + <reg name="r22" bitsize="64"/> + <reg name="r23" bitsize="64"/> + <reg name="r24" bitsize="64"/> + <reg name="r25" bitsize="64"/> + <reg name="r26" bitsize="64"/> + <reg name="r27" bitsize="64"/> + <reg name="r28" bitsize="64"/> + <reg name="r29" bitsize="64"/> + <reg name="r30" bitsize="64"/> + <reg name="r31" bitsize="64"/> + + <reg name="lo" bitsize="64" regnum="33"/> + <reg name="hi" bitsize="64" regnum="34"/> + <reg name="pc" bitsize="64" regnum="37"/> +</feature> diff --git a/gdb/features/mips64-fpu.xml b/gdb/features/mips64-fpu.xml new file mode 100644 index 0000000..f79d33f --- /dev/null +++ b/gdb/features/mips64-fpu.xml @@ -0,0 +1,45 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2007 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.mips.fpu"> + <reg name="f0" bitsize="64" type="ieee_double"/> + <reg name="f1" bitsize="64" type="ieee_double"/> + <reg name="f2" bitsize="64" type="ieee_double"/> + <reg name="f3" bitsize="64" type="ieee_double"/> + <reg name="f4" bitsize="64" type="ieee_double"/> + <reg name="f5" bitsize="64" type="ieee_double"/> + <reg name="f6" bitsize="64" type="ieee_double"/> + <reg name="f7" bitsize="64" type="ieee_double"/> + <reg name="f8" bitsize="64" type="ieee_double"/> + <reg name="f9" bitsize="64" type="ieee_double"/> + <reg name="f10" bitsize="64" type="ieee_double"/> + <reg name="f11" bitsize="64" type="ieee_double"/> + <reg name="f12" bitsize="64" type="ieee_double"/> + <reg name="f13" bitsize="64" type="ieee_double"/> + <reg name="f14" bitsize="64" type="ieee_double"/> + <reg name="f15" bitsize="64" type="ieee_double"/> + <reg name="f16" bitsize="64" type="ieee_double"/> + <reg name="f17" bitsize="64" type="ieee_double"/> + <reg name="f18" bitsize="64" type="ieee_double"/> + <reg name="f19" bitsize="64" type="ieee_double"/> + <reg name="f20" bitsize="64" type="ieee_double"/> + <reg name="f21" bitsize="64" type="ieee_double"/> + <reg name="f22" bitsize="64" type="ieee_double"/> + <reg name="f23" bitsize="64" type="ieee_double"/> + <reg name="f24" bitsize="64" type="ieee_double"/> + <reg name="f25" bitsize="64" type="ieee_double"/> + <reg name="f26" bitsize="64" type="ieee_double"/> + <reg name="f27" bitsize="64" type="ieee_double"/> + <reg name="f28" bitsize="64" type="ieee_double"/> + <reg name="f29" bitsize="64" type="ieee_double"/> + <reg name="f30" bitsize="64" type="ieee_double"/> + <reg name="f31" bitsize="64" type="ieee_double"/> + + <reg name="fcsr" bitsize="64" group="float"/> + <reg name="fir" bitsize="64" group="float"/> +</feature> diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index c1c7e72..72268fd 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -58,6 +58,7 @@ #include "remote.h" #include "target-descriptions.h" #include "dwarf2-frame.h" +#include "user-regs.h" static const struct objfile_data *mips_pdr_data; @@ -94,6 +95,55 @@ static const char *mips_abi_strings[] = { NULL }; +/* The standard register names, and all the valid aliases for them. */ +struct register_alias +{ + const char *name; + int regnum; +}; + +/* Aliases for o32 and most other ABIs. */ +const struct register_alias mips_o32_aliases[] = { + { "ta0", 12 }, + { "ta1", 13 }, + { "ta2", 14 }, + { "ta3", 15 } +}; + +/* Aliases for n32 and n64. */ +const struct register_alias mips_n32_n64_aliases[] = { + { "ta0", 8 }, + { "ta1", 9 }, + { "ta2", 10 }, + { "ta3", 11 } +}; + +/* Aliases for ABI-independent registers. */ +const struct register_alias mips_register_aliases[] = { + /* The architecture manuals specify these ABI-independent names for + the GPRs. */ +#define R(n) { "r" #n, n } + R(0), R(1), R(2), R(3), R(4), R(5), R(6), R(7), + R(8), R(9), R(10), R(11), R(12), R(13), R(14), R(15), + R(16), R(17), R(18), R(19), R(20), R(21), R(22), R(23), + R(24), R(25), R(26), R(27), R(28), R(29), R(30), R(31), +#undef R + + /* k0 and k1 are sometimes called these instead (for "kernel + temp"). */ + { "kt0", 26 }, + { "kt1", 27 }, + + /* This is the traditional GDB name for the CP0 status register. */ + { "sr", MIPS_PS_REGNUM }, + + /* This is the traditional GDB name for the CP0 BadVAddr register. */ + { "bad", MIPS_EMBED_BADVADDR_REGNUM }, + + /* This is the traditional GDB name for the FCSR. */ + { "fsr", MIPS_EMBED_FP0_REGNUM + 32 } +}; + /* Some MIPS boards don't support floating point while others only support single-precision floating-point operations. */ @@ -509,6 +559,8 @@ mips_register_name (int regno) else return mips_gpr_names[rawnum]; } + else if (tdesc_has_registers (gdbarch_target_desc (current_gdbarch))) + return tdesc_register_name (rawnum); else if (32 <= rawnum && rawnum < gdbarch_num_regs (current_gdbarch)) { gdb_assert (rawnum - 32 < NUM_MIPS_PROCESSOR_REGS); @@ -557,6 +609,35 @@ mips_register_reggroup_p (struct gdbarch *gdbarch, int regnum, return 0; } +/* Return the groups that a MIPS register can be categorised into. + This version is only used if we have a target description which + describes real registers (and their groups). */ + +static int +mips_tdesc_register_reggroup_p (struct gdbarch *gdbarch, int regnum, + struct reggroup *reggroup) +{ + int rawnum = regnum % gdbarch_num_regs (gdbarch); + int pseudo = regnum / gdbarch_num_regs (gdbarch); + int ret; + + /* Only save, restore, and display the pseudo registers. Need to + make certain that any code extracting register values from a + saved register cache also uses pseudo registers. + + Note: saving and restoring the pseudo registers is slightly + strange; if we have 64 bits, we should save and restore all + 64 bits. But this is hard and has little benefit. */ + if (!pseudo) + return 0; + + ret = tdesc_register_in_reggroup_p (gdbarch, rawnum, reggroup); + if (ret != -1) + return ret; + + return mips_register_reggroup_p (gdbarch, regnum, reggroup); +} + /* Map the symbol table registers which live in the range [1 * gdbarch_num_regs .. 2 * gdbarch_num_regs) back onto the corresponding raw registers. Take care of alignment and size problems. */ @@ -721,6 +802,59 @@ mips_register_type (struct gdbarch *gdbarch, int regnum) } } +/* Return the GDB type for the pseudo register REGNUM, which is the + ABI-level view. This function is only called if there is a target + description which includes registers, so we know precisely the + types of hardware registers. */ + +static struct type * +mips_pseudo_register_type (struct gdbarch *gdbarch, int regnum) +{ + const int num_regs = gdbarch_num_regs (gdbarch); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int rawnum = regnum % num_regs; + struct type *rawtype; + + gdb_assert (regnum >= num_regs && regnum < 2 * num_regs); + + /* Absent registers are still absent. */ + rawtype = gdbarch_register_type (gdbarch, rawnum); + if (TYPE_LENGTH (rawtype) == 0) + return rawtype; + + if (rawnum >= MIPS_EMBED_FP0_REGNUM && rawnum < MIPS_EMBED_FP0_REGNUM + 32) + /* Present the floating point registers however the hardware did; + do not try to convert between FPU layouts. */ + return rawtype; + + if (rawnum >= MIPS_EMBED_FP0_REGNUM + 32 && rawnum <= MIPS_LAST_EMBED_REGNUM) + { + /* The pseudo/cooked view of embedded registers is always + 32-bit, even if the target transfers 64-bit values for them. + New targets relying on XML descriptions should only transfer + the necessary 32 bits, but older versions of GDB expected 64, + so allow the target to provide 64 bits without interfering + with the displayed type. */ + return builtin_type_int32; + } + + /* Use pointer types for registers if we can. For n32 we can not, + since we do not have a 64-bit pointer type. */ + if (mips_abi_regsize (gdbarch) == TYPE_LENGTH (builtin_type_void_data_ptr)) + { + if (rawnum == MIPS_SP_REGNUM || rawnum == MIPS_EMBED_BADVADDR_REGNUM) + return builtin_type_void_data_ptr; + else if (rawnum == MIPS_EMBED_PC_REGNUM) + return builtin_type_void_func_ptr; + } + + if (mips_abi_regsize (gdbarch) == 4 && TYPE_LENGTH (rawtype) == 8 + && rawnum >= MIPS_ZERO_REGNUM && rawnum <= MIPS_EMBED_PC_REGNUM) + return builtin_type_int32; + + /* For all other registers, pass through the hardware type. */ + return rawtype; +} /* Should the upper word of 64-bit addresses be zeroed? */ enum auto_boolean mask_address_var = AUTO_BOOLEAN_AUTO; @@ -4724,6 +4858,13 @@ mips_register_g_packet_guesses (struct gdbarch *gdbarch) /* Otherwise we don't have a useful guess. */ } +static struct value * +value_of_mips_user_reg (struct frame_info *frame, const void *baton) +{ + const int *reg_p = baton; + return value_of_register (*reg_p, frame); +} + static struct gdbarch * mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { @@ -4731,8 +4872,108 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) struct gdbarch_tdep *tdep; int elf_flags; enum mips_abi mips_abi, found_abi, wanted_abi; - int num_regs; + int i, num_regs; enum mips_fpu_type fpu_type; + struct tdesc_arch_data *tdesc_data = NULL; + + /* Check any target description for validity. */ + if (tdesc_has_registers (info.target_desc)) + { + static const char *const mips_gprs[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" + }; + static const char *const mips_fprs[] = { + "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", + }; + + const struct tdesc_feature *feature; + int valid_p; + + feature = tdesc_find_feature (info.target_desc, + "org.gnu.gdb.mips.cpu"); + if (feature == NULL) + return NULL; + + tdesc_data = tdesc_data_alloc (); + + valid_p = 1; + for (i = MIPS_ZERO_REGNUM; i <= MIPS_RA_REGNUM; i++) + valid_p &= tdesc_numbered_register (feature, tdesc_data, i, + mips_gprs[i]); + + + valid_p &= tdesc_numbered_register (feature, tdesc_data, + MIPS_EMBED_LO_REGNUM, "lo"); + valid_p &= tdesc_numbered_register (feature, tdesc_data, + MIPS_EMBED_HI_REGNUM, "hi"); + valid_p &= tdesc_numbered_register (feature, tdesc_data, + MIPS_EMBED_PC_REGNUM, "pc"); + + if (!valid_p) + { + tdesc_data_cleanup (tdesc_data); + return NULL; + } + + feature = tdesc_find_feature (info.target_desc, + "org.gnu.gdb.mips.cp0"); + if (feature == NULL) + { + tdesc_data_cleanup (tdesc_data); + return NULL; + } + + valid_p = 1; + valid_p &= tdesc_numbered_register (feature, tdesc_data, + MIPS_EMBED_BADVADDR_REGNUM, + "badvaddr"); + valid_p &= tdesc_numbered_register (feature, tdesc_data, + MIPS_PS_REGNUM, "status"); + valid_p &= tdesc_numbered_register (feature, tdesc_data, + MIPS_EMBED_CAUSE_REGNUM, "cause"); + + if (!valid_p) + { + tdesc_data_cleanup (tdesc_data); + return NULL; + } + + /* FIXME drow/2007-05-17: The FPU should be optional. The MIPS + backend is not prepared for that, though. */ + feature = tdesc_find_feature (info.target_desc, + "org.gnu.gdb.mips.fpu"); + if (feature == NULL) + { + tdesc_data_cleanup (tdesc_data); + return NULL; + } + + valid_p = 1; + for (i = 0; i < 32; i++) + valid_p &= tdesc_numbered_register (feature, tdesc_data, + i + MIPS_EMBED_FP0_REGNUM, + mips_fprs[i]); + + valid_p &= tdesc_numbered_register (feature, tdesc_data, + MIPS_EMBED_FP0_REGNUM + 32, "fcsr"); + valid_p &= tdesc_numbered_register (feature, tdesc_data, + MIPS_EMBED_FP0_REGNUM + 33, "fir"); + + if (!valid_p) + { + tdesc_data_cleanup (tdesc_data); + return NULL; + } + + /* It would be nice to detect an attempt to use a 64-bit ABI + when only 32-bit registers are provided. */ + } /* First of all, extract the elf_flags, if available. */ if (info.abfd && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour) @@ -4876,7 +5117,11 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) && tdesc_property (info.target_desc, PROPERTY_GP32) != NULL && mips_abi != MIPS_ABI_EABI32 && mips_abi != MIPS_ABI_O32) - return NULL; + { + if (tdesc_data != NULL) + tdesc_data_cleanup (tdesc_data); + return NULL; + } /* try to find a pre-existing architecture */ for (arches = gdbarch_list_lookup_by_info (arches, &info); @@ -4897,6 +5142,9 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Be pedantic about which FPU is selected. */ if (gdbarch_tdep (arches->gdbarch)->mips_fpu_type != fpu_type) continue; + + if (tdesc_data != NULL) + tdesc_data_cleanup (tdesc_data); return arches->gdbarch; } @@ -4944,7 +5192,20 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) const char **reg_names; struct mips_regnum *regnum = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct mips_regnum); - if (info.osabi == GDB_OSABI_IRIX) + if (tdesc_has_registers (info.target_desc)) + { + regnum->lo = MIPS_EMBED_LO_REGNUM; + regnum->hi = MIPS_EMBED_HI_REGNUM; + regnum->badvaddr = MIPS_EMBED_BADVADDR_REGNUM; + regnum->cause = MIPS_EMBED_CAUSE_REGNUM; + regnum->pc = MIPS_EMBED_PC_REGNUM; + regnum->fp0 = MIPS_EMBED_FP0_REGNUM; + regnum->fp_control_status = 70; + regnum->fp_implementation_revision = 71; + num_regs = MIPS_LAST_EMBED_REGNUM + 1; + reg_names = NULL; + } + else if (info.osabi == GDB_OSABI_IRIX) { regnum->fp0 = 32; regnum->pc = 64; @@ -5208,6 +5469,37 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) frame_base_append_sniffer (gdbarch, mips_insn16_frame_base_sniffer); frame_base_append_sniffer (gdbarch, mips_insn32_frame_base_sniffer); + if (tdesc_data) + { + set_tdesc_pseudo_register_type (gdbarch, mips_pseudo_register_type); + tdesc_use_registers (gdbarch, tdesc_data); + + /* Override the normal target description methods to handle our + dual real and pseudo registers. */ + set_gdbarch_register_name (gdbarch, mips_register_name); + set_gdbarch_register_reggroup_p (gdbarch, mips_tdesc_register_reggroup_p); + + num_regs = gdbarch_num_regs (gdbarch); + set_gdbarch_num_pseudo_regs (gdbarch, num_regs); + set_gdbarch_pc_regnum (gdbarch, tdep->regnum->pc + num_regs); + set_gdbarch_sp_regnum (gdbarch, MIPS_SP_REGNUM + num_regs); + } + + /* Add ABI-specific aliases for the registers. */ + if (mips_abi == MIPS_ABI_N32 || mips_abi == MIPS_ABI_N64) + for (i = 0; i < ARRAY_SIZE (mips_n32_n64_aliases); i++) + user_reg_add (gdbarch, mips_n32_n64_aliases[i].name, + value_of_mips_user_reg, &mips_n32_n64_aliases[i].regnum); + else + for (i = 0; i < ARRAY_SIZE (mips_o32_aliases); i++) + user_reg_add (gdbarch, mips_o32_aliases[i].name, + value_of_mips_user_reg, &mips_o32_aliases[i].regnum); + + /* Add some other standard aliases. */ + for (i = 0; i < ARRAY_SIZE (mips_register_aliases); i++) + user_reg_add (gdbarch, mips_register_aliases[i].name, + value_of_mips_user_reg, &mips_register_aliases[i].regnum); + return gdbarch; } diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c index e8b7cbc..6df4547 100644 --- a/gdb/target-descriptions.c +++ b/gdb/target-descriptions.c @@ -486,7 +486,10 @@ tdesc_find_register (struct gdbarch *gdbarch, int regno) return NULL; } -static const char * +/* Return the name of register REGNO, from the target description or + from an architecture-provided pseudo_register_name method. */ + +const char * tdesc_register_name (int regno) { struct tdesc_reg *reg = tdesc_find_register (current_gdbarch, regno); @@ -582,8 +585,9 @@ tdesc_remote_register_number (struct gdbarch *gdbarch, int regno) /* Check whether REGNUM is a member of REGGROUP. Registers from the target description may be classified as general, float, or vector. - Registers with no group specified go to the default reggroup - function and are handled by type. + Unlike a gdbarch register_reggroup_p method, this function will + return -1 if it does not know; the caller should handle registers + with no specified group. Arbitrary strings (other than "general", "float", and "vector") from the description are not used; they cause the register to be @@ -594,21 +598,12 @@ tdesc_remote_register_number (struct gdbarch *gdbarch, int regno) The save-restore flag is also implemented here. */ -static int -tdesc_register_reggroup_p (struct gdbarch *gdbarch, int regno, - struct reggroup *reggroup) +int +tdesc_register_in_reggroup_p (struct gdbarch *gdbarch, int regno, + struct reggroup *reggroup) { - int num_regs = gdbarch_num_regs (gdbarch); - int num_pseudo_regs = gdbarch_num_pseudo_regs (gdbarch); struct tdesc_reg *reg = tdesc_find_register (gdbarch, regno); - if (reg == NULL && regno >= num_regs && regno < num_regs + num_pseudo_regs) - { - struct tdesc_arch_data *data = gdbarch_data (gdbarch, tdesc_data); - gdb_assert (data->pseudo_register_reggroup_p != NULL); - return data->pseudo_register_reggroup_p (gdbarch, regno, reggroup); - } - if (reg != NULL && reg->group != NULL) { int general_p = 0, float_p = 0, vector_p = 0; @@ -634,6 +629,32 @@ tdesc_register_reggroup_p (struct gdbarch *gdbarch, int regno, && (reggroup == save_reggroup || reggroup == restore_reggroup)) return reg->save_restore; + return -1; +} + +/* Check whether REGNUM is a member of REGGROUP. Registers with no + group specified go to the default reggroup function and are handled + by type. */ + +static int +tdesc_register_reggroup_p (struct gdbarch *gdbarch, int regno, + struct reggroup *reggroup) +{ + int num_regs = gdbarch_num_regs (gdbarch); + int num_pseudo_regs = gdbarch_num_pseudo_regs (gdbarch); + int ret; + + if (regno >= num_regs && regno < num_regs + num_pseudo_regs) + { + struct tdesc_arch_data *data = gdbarch_data (gdbarch, tdesc_data); + gdb_assert (data->pseudo_register_reggroup_p != NULL); + return data->pseudo_register_reggroup_p (gdbarch, regno, reggroup); + } + + ret = tdesc_register_in_reggroup_p (gdbarch, regno, reggroup); + if (ret != -1) + return ret; + return default_register_reggroup_p (gdbarch, regno, reggroup); } diff --git a/gdb/target-descriptions.h b/gdb/target-descriptions.h index 575b349..d6d6714 100644 --- a/gdb/target-descriptions.h +++ b/gdb/target-descriptions.h @@ -140,6 +140,18 @@ const char *tdesc_feature_name (const struct tdesc_feature *feature); struct type *tdesc_named_type (const struct tdesc_feature *feature, const char *id); +/* Return the name of register REGNO, from the target description or + from an architecture-provided pseudo_register_name method. */ + +const char *tdesc_register_name (int regno); + +/* Check whether REGNUM is a member of REGGROUP using the target + description. Return -1 if the target description does not + specify a group. */ + +int tdesc_register_in_reggroup_p (struct gdbarch *gdbarch, int regno, + struct reggroup *reggroup); + /* Methods for constructing a target description. */ struct target_desc *allocate_target_description (void); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index cf5d3b4..d1b22a4 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-06-13 Daniel Jacobowitz <dan@codesourcery.com> + + * gdb.xml/tdesc-regs.exp: Add MIPS support. Allow multiple + required features to be included. + 2007-06-12 Daniel Jacobowitz <dan@codesourcery.com> * gdb.threads/manythreads.exp: Prevent expect buffer overflow diff --git a/gdb/testsuite/gdb.xml/tdesc-regs.exp b/gdb/testsuite/gdb.xml/tdesc-regs.exp index fde2111..43d6c99 100644 --- a/gdb/testsuite/gdb.xml/tdesc-regs.exp +++ b/gdb/testsuite/gdb.xml/tdesc-regs.exp @@ -27,10 +27,13 @@ gdb_start set core-regs "" switch -glob -- [istarget] { "*arm-*-*" { - set core-regs arm-core + set core-regs {arm-core.xml} } "xscale-*-*" { - set core-regs arm-core + set core-regs {arm-core.xml} + } + "mips*-*-*" { + set core-regs {mips-cpu.xml mips-cp0.xml mips-fpu.xml} } } @@ -56,17 +59,32 @@ gdb_test "set tdesc file $srcdir/$subdir/single-reg.xml" \ # Copy the core registers into the objdir if necessary, so that they # will be found by <xi:include>. -file delete "core-regs.xml" -file copy "$srcdir/../features/${core-regs}.xml" "core-regs.xml" +foreach src ${core-regs} { + file delete "$src" + file copy "$srcdir/../features/$src" "$src" +} # Similarly, we need to copy files under test into the objdir. proc load_description { file errmsg } { global srcdir global subdir global gdb_prompt + global core-regs file delete "regs.xml" - file copy "$srcdir/$subdir/$file" "regs.xml" + set ifd [open "$srcdir/$subdir/$file" r] + set ofd [open "regs.xml" w] + while {[gets $ifd line] >= 0} { + if {[regexp {<xi:include href="core-regs.xml"/>} $line]} { + foreach src ${core-regs} { + puts $ofd " <xi:include href=\"$src\"/>" + } + } else { + puts $ofd $line + } + } + close $ifd + close $ofd # Anchor the test output, so that error messages are detected. set cmd "set tdesc filename regs.xml" @@ -91,5 +109,7 @@ load_description "core-only.xml" "" # The extra register from the previous description should be gone. gdb_test "ptype \$extrareg" "type = void" -file delete "core-regs.xml" +foreach src ${core-regs} { + file delete "$src" +} file delete "regs.xml" |