diff options
author | Maciej W. Rozycki <macro@linux-mips.org> | 2012-03-01 22:19:48 +0000 |
---|---|---|
committer | Maciej W. Rozycki <macro@linux-mips.org> | 2012-03-01 22:19:48 +0000 |
commit | 1faeff088bbbd037d7769d214378b4faf805fa2e (patch) | |
tree | 8cb63635e8ec7e66e95a6224b52c725e8149305d /gdb/mips-tdep.c | |
parent | f3b4f45c3398591eed0bf54bb2a51266aa8a2c4a (diff) | |
download | gdb-1faeff088bbbd037d7769d214378b4faf805fa2e.zip gdb-1faeff088bbbd037d7769d214378b4faf805fa2e.tar.gz gdb-1faeff088bbbd037d7769d214378b4faf805fa2e.tar.bz2 |
gdb/
* features/mips-dsp.xml: New file.
* features/mips64-dsp.xml: New file.
* features/mips-dsp-linux.xml: New file.
* features/mips64-dsp-linux.xml: New file.
* features/Makefile (WHICH): Add mips-dsp-linux and
mips64-dsp-linux.
(mips-dsp-expedite, mips64-dsp-expedite): New variables.
* features/mips-dsp-linux.c: New file.
* features/mips64-dsp-linux.c: New file.
* regformats/mips-dsp-linux.dat: New file.
* regformats/mips64-dsp-linux.dat: New file.
* mips-linux-nat.c (mips_linux_register_addr): Handle DSP
registers.
(mips64_linux_register_addr): Likewise.
(mips64_linux_regsets_fetch_registers): Likewise.
(mips64_linux_regsets_store_registers): Likewise.
(mips64_linux_fetch_registers): Update call to
mips64_linux_regsets_fetch_registers.
(mips64_linux_store_registers): Update call to
mips64_linux_regsets_store_registers.
(mips_linux_read_description): Probe for DSP registers.
(_initialize_mips_linux_nat): Call initialize_tdesc_mips_dsp_linux
and initialize_tdesc_mips64_dsp_linux.
* mips-linux-tdep.c (supply_gregset, mips64_supply_gregset):
Remove padding of no longer used embedded register slots.
* mips-linux-tdep.h (DSP_BASE, DSP_CONTROL): New macros.
(MIPS_RESTART_REGNUM): Redefine enum value.
* mips-tdep.c (mips_generic_reg_names): Remove trailing null
strings.
(mips_tx39_reg_names): Likewise.
(mips_linux_reg_names): New array of register names for Linux
targets.
(mips_register_name): Check for a null pointer in
mips_processor_reg_names and return an empty string.
(mips_register_type): Exclude embedded registers for the IRIX
and Linux ABIs.
(mips_pseudo_register_type): Likewise. Use dynamic numbers to
refer to FP registers, LO, HI, BadVAddr, Cause and PC. Handle
DSP registers.
(mips_stab_reg_to_regnum): Handle DSP accumulators.
(mips_dwarf_dwarf2_ecoff_reg_to_regnum): Likewise.
(mips_gdbarch_init): Likewise. Initialize internal register
indices for the Linux ABI. Use dynamic numbers to refer to
registers, as applicable, while parsing the target description.
* mips-tdep.h (struct mips_regnum): Add dspacc/dspctl offsets.
gdb/doc/
* gdb.texinfo (MIPS Features): Add org.gnu.gdb.mips.dsp.
gdb/gdbserver/
* linux-low.h (linux_target_ops): Add regset_bitmap member.
* linux-low.c (use_linux_regsets): New macro.
[!HAVE_LINUX_REGSETS] (regsets_fetch_inferior_registers): Likewise.
[!HAVE_LINUX_REGSETS] (regsets_store_inferior_registers): Likewise.
(linux_register_in_regsets): New function.
(usr_fetch_inferior_registers): Skip registers covered by
regsets.
(usr_store_inferior_registers): Likewise.
(usr_fetch_inferior_registers): New macro.
(usr_store_inferior_registers): Likewise.
(linux_fetch_registers): Handle mixed regset/non-regset targets.
(linux_store_registers): Likewise.
* linux-mips-low.c (init_registers_mips_dsp_linux): New
prototype.
(init_registers_mips64_dsp_linux): Likewise.
(init_registers_mips_linux): New macro.
(init_registers_mips_dsp_linux): Likewise.
(mips_dsp_num_regs): Likewise.
(DSP_BASE, DSP_CONTROL): New fallback macros.
(mips_base_regs): New macro.
(mips_regmap): Use it. Fix the size.
(mips_dsp_regmap): New variable.
(mips_dsp_regset_bitmap): Likewise.
(mips_arch_setup): New function.
(mips_cannot_fetch_register): Use the_low_target.regmap rather
than mips_regmap.
(mips_cannot_store_register): Likewise.
(the_low_target): Update .arch_setup, .num_regs and .regmap
initializers. Add .regset_bitmap initializer.
* linux-arm-low.c (the_low_target): Add .regset_bitmap
initializer.
* linux-bfin-low.c (the_low_target): Likewise.
* linux-cris-low.c (the_low_target): Likewise.
* linux-crisv32-low.c (the_low_target): Likewise.
* linux-ia64-low.c (the_low_target): Likewise.
* linux-m32r-low.c (the_low_target): Likewise.
* linux-m68k-low.c (the_low_target): Likewise.
* linux-ppc-low.c (the_low_target): Likewise.
* linux-s390-low.c (the_low_target): Likewise.
* linux-sh-low.c (the_low_target): Likewise.
* linux-sparc-low.c (the_low_target): Likewise.
* linux-tic6x-low.c (the_low_target): Likewise.
* linux-x86-low.c (the_low_target): Likewise.
* linux-xtensa-low.c (the_low_target): Likewise.
* configure.srv <mips*-*-linux*>: Add mips-dsp-linux.o and
mips64-dsp-linux.o to srv_regobj. Add mips-dsp-linux.xml,
mips64-dsp-linux.xml, mips-dsp.xml and mips64-dsp.xml to
srv_xmlfiles.
* Makefile.in (mips-dsp-linux.o, mips-dsp-linux.c): New targets.
(mips64-dsp-linux.o, mips64-dsp-linux.c): Likewise.
gdb/testsuite/
* gdb.xml/tdesc-regs.exp: Add "mips-dsp.xml" to the list of MIPS
core registers.
Diffstat (limited to 'gdb/mips-tdep.c')
-rw-r--r-- | gdb/mips-tdep.c | 269 |
1 files changed, 175 insertions, 94 deletions
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index 67ead3c..3e09d5c 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -390,9 +390,7 @@ static const char *mips_generic_reg_names[NUM_MIPS_PROCESSOR_REGS] = { "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" */ , "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", + "fsr", "fir", }; /* Names of IDT R3041 registers. */ @@ -418,7 +416,7 @@ static const char *mips_tx39_reg_names[NUM_MIPS_PROCESSOR_REGS] = { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", - "", "", "config", "cache", "debug", "depc", "epc", "" + "", "", "config", "cache", "debug", "depc", "epc", }; /* Names of IRIX registers. */ @@ -430,6 +428,16 @@ static const char *mips_irix_reg_names[NUM_MIPS_PROCESSOR_REGS] = { "pc", "cause", "bad", "hi", "lo", "fsr", "fir" }; +/* Names of Linux registers. */ +static const char *mips_linux_reg_names[NUM_MIPS_PROCESSOR_REGS] = { + "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" +}; + /* Return the name of the register corresponding to REGNO. */ static const char * @@ -484,7 +492,9 @@ mips_register_name (struct gdbarch *gdbarch, int regno) else if (32 <= rawnum && rawnum < gdbarch_num_regs (gdbarch)) { gdb_assert (rawnum - 32 < NUM_MIPS_PROCESSOR_REGS); - return tdep->mips_processor_reg_names[rawnum - 32]; + if (tdep->mips_processor_reg_names[rawnum - 32]) + return tdep->mips_processor_reg_names[rawnum - 32]; + return ""; } else internal_error (__FILE__, __LINE__, @@ -854,11 +864,17 @@ mips_register_type (struct gdbarch *gdbarch, int regnum) } else { + int rawnum = regnum - gdbarch_num_regs (gdbarch); + /* The cooked or ABI registers. These are sized according to the ABI (with a few complications). */ - if (regnum >= (gdbarch_num_regs (gdbarch) - + mips_regnum (gdbarch)->fp_control_status) - && regnum <= gdbarch_num_regs (gdbarch) + MIPS_LAST_EMBED_REGNUM) + if (rawnum == mips_regnum (gdbarch)->fp_control_status + || rawnum == mips_regnum (gdbarch)->fp_implementation_revision) + return builtin_type (gdbarch)->builtin_int32; + else if (gdbarch_osabi (gdbarch) != GDB_OSABI_IRIX + && gdbarch_osabi (gdbarch) != GDB_OSABI_LINUX + && rawnum >= MIPS_FIRST_EMBED_REGNUM + && rawnum <= MIPS_LAST_EMBED_REGNUM) /* The pseudo/cooked view of the embedded registers is always 32-bit. The raw view is handled below. */ return builtin_type (gdbarch)->builtin_int32; @@ -897,37 +913,50 @@ mips_pseudo_register_type (struct gdbarch *gdbarch, int regnum) if (TYPE_LENGTH (rawtype) == 0) return rawtype; - if (rawnum >= MIPS_EMBED_FP0_REGNUM && rawnum < MIPS_EMBED_FP0_REGNUM + 32) + if (rawnum >= mips_regnum (gdbarch)->fp0 + && rawnum < mips_regnum (gdbarch)->fp0 + 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 (gdbarch)->builtin_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 (gdbarch)->builtin_data_ptr)) { - if (rawnum == MIPS_SP_REGNUM || rawnum == MIPS_EMBED_BADVADDR_REGNUM) + if (rawnum == MIPS_SP_REGNUM + || rawnum == mips_regnum (gdbarch)->badvaddr) return builtin_type (gdbarch)->builtin_data_ptr; - else if (rawnum == MIPS_EMBED_PC_REGNUM) + else if (rawnum == mips_regnum (gdbarch)->pc) return builtin_type (gdbarch)->builtin_func_ptr; } if (mips_abi_regsize (gdbarch) == 4 && TYPE_LENGTH (rawtype) == 8 - && rawnum >= MIPS_ZERO_REGNUM && rawnum <= MIPS_EMBED_PC_REGNUM) + && ((rawnum >= MIPS_ZERO_REGNUM && rawnum <= MIPS_PS_REGNUM) + || rawnum == mips_regnum (gdbarch)->lo + || rawnum == mips_regnum (gdbarch)->hi + || rawnum == mips_regnum (gdbarch)->badvaddr + || rawnum == mips_regnum (gdbarch)->cause + || rawnum == mips_regnum (gdbarch)->pc + || (mips_regnum (gdbarch)->dspacc != -1 + && rawnum >= mips_regnum (gdbarch)->dspacc + && rawnum < mips_regnum (gdbarch)->dspacc + 6))) return builtin_type (gdbarch)->builtin_int32; + if (gdbarch_osabi (gdbarch) != GDB_OSABI_IRIX + && gdbarch_osabi (gdbarch) != GDB_OSABI_LINUX + && 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 (gdbarch)->builtin_int32; + } + /* For all other registers, pass through the hardware type. */ return rawtype; } @@ -5715,6 +5744,8 @@ mips_stab_reg_to_regnum (struct gdbarch *gdbarch, int num) regnum = mips_regnum (gdbarch)->hi; else if (num == 71) regnum = mips_regnum (gdbarch)->lo; + else if (mips_regnum (gdbarch)->dspacc != -1 && num >= 72 && num < 78) + regnum = num + mips_regnum (gdbarch)->dspacc - 72; else /* This will hopefully (eventually) provoke a warning. Should we be calling complaint() here? */ @@ -5738,6 +5769,8 @@ mips_dwarf_dwarf2_ecoff_reg_to_regnum (struct gdbarch *gdbarch, int num) regnum = mips_regnum (gdbarch)->hi; else if (num == 65) regnum = mips_regnum (gdbarch)->lo; + else if (mips_regnum (gdbarch)->dspacc != -1 && num >= 66 && num < 72) + regnum = num + mips_regnum (gdbarch)->dspacc - 66; else /* This will hopefully (eventually) provoke a warning. Should we be calling complaint() here? */ @@ -5877,6 +5910,63 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) enum mips_fpu_type fpu_type; struct tdesc_arch_data *tdesc_data = NULL; int elf_fpu_type = 0; + const char **reg_names; + struct mips_regnum mips_regnum, *regnum; + int dspacc; + int dspctl; + + /* Fill in the OS dependent register numbers and names. */ + if (info.osabi == GDB_OSABI_IRIX) + { + mips_regnum.fp0 = 32; + mips_regnum.pc = 64; + mips_regnum.cause = 65; + mips_regnum.badvaddr = 66; + mips_regnum.hi = 67; + mips_regnum.lo = 68; + mips_regnum.fp_control_status = 69; + mips_regnum.fp_implementation_revision = 70; + mips_regnum.dspacc = dspacc = -1; + mips_regnum.dspctl = dspctl = -1; + num_regs = 71; + reg_names = mips_irix_reg_names; + } + else if (info.osabi == GDB_OSABI_LINUX) + { + mips_regnum.fp0 = 38; + mips_regnum.pc = 37; + mips_regnum.cause = 36; + mips_regnum.badvaddr = 35; + mips_regnum.hi = 34; + mips_regnum.lo = 33; + mips_regnum.fp_control_status = 70; + mips_regnum.fp_implementation_revision = 71; + mips_regnum.dspacc = -1; + mips_regnum.dspctl = -1; + dspacc = 72; + dspctl = 78; + num_regs = 79; + reg_names = mips_linux_reg_names; + } + else + { + mips_regnum.lo = MIPS_EMBED_LO_REGNUM; + mips_regnum.hi = MIPS_EMBED_HI_REGNUM; + mips_regnum.badvaddr = MIPS_EMBED_BADVADDR_REGNUM; + mips_regnum.cause = MIPS_EMBED_CAUSE_REGNUM; + mips_regnum.pc = MIPS_EMBED_PC_REGNUM; + mips_regnum.fp0 = MIPS_EMBED_FP0_REGNUM; + mips_regnum.fp_control_status = 70; + mips_regnum.fp_implementation_revision = 71; + mips_regnum.dspacc = dspacc = -1; + mips_regnum.dspctl = dspctl = -1; + num_regs = MIPS_LAST_EMBED_REGNUM + 1; + if (info.bfd_arch_info != NULL + && info.bfd_arch_info->mach == bfd_mach_mips3900) + reg_names = mips_tx39_reg_names; + else + reg_names = mips_generic_reg_names; + } /* Check any target description for validity. */ if (tdesc_has_registers (info.target_desc)) @@ -5911,11 +6001,11 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) valid_p &= tdesc_numbered_register (feature, tdesc_data, - MIPS_EMBED_LO_REGNUM, "lo"); + mips_regnum.lo, "lo"); valid_p &= tdesc_numbered_register (feature, tdesc_data, - MIPS_EMBED_HI_REGNUM, "hi"); + mips_regnum.hi, "hi"); valid_p &= tdesc_numbered_register (feature, tdesc_data, - MIPS_EMBED_PC_REGNUM, "pc"); + mips_regnum.pc, "pc"); if (!valid_p) { @@ -5933,12 +6023,11 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) valid_p = 1; valid_p &= tdesc_numbered_register (feature, tdesc_data, - MIPS_EMBED_BADVADDR_REGNUM, - "badvaddr"); + mips_regnum.badvaddr, "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"); + mips_regnum.cause, "cause"); if (!valid_p) { @@ -5959,13 +6048,15 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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]); + i + mips_regnum.fp0, 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"); + mips_regnum.fp_control_status, + "fcsr"); + valid_p + &= tdesc_numbered_register (feature, tdesc_data, + mips_regnum.fp_implementation_revision, + "fir"); if (!valid_p) { @@ -5973,8 +6064,45 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) return NULL; } + if (dspacc >= 0) + { + feature = tdesc_find_feature (info.target_desc, + "org.gnu.gdb.mips.dsp"); + /* The DSP registers are optional; it's OK if they are absent. */ + if (feature != NULL) + { + i = 0; + valid_p = 1; + valid_p &= tdesc_numbered_register (feature, tdesc_data, + dspacc + i++, "hi1"); + valid_p &= tdesc_numbered_register (feature, tdesc_data, + dspacc + i++, "lo1"); + valid_p &= tdesc_numbered_register (feature, tdesc_data, + dspacc + i++, "hi2"); + valid_p &= tdesc_numbered_register (feature, tdesc_data, + dspacc + i++, "lo2"); + valid_p &= tdesc_numbered_register (feature, tdesc_data, + dspacc + i++, "hi3"); + valid_p &= tdesc_numbered_register (feature, tdesc_data, + dspacc + i++, "lo3"); + + valid_p &= tdesc_numbered_register (feature, tdesc_data, + dspctl, "dspctl"); + + if (!valid_p) + { + tdesc_data_cleanup (tdesc_data); + return NULL; + } + + mips_regnum.dspacc = dspacc; + mips_regnum.dspctl = dspctl; + } + } + /* It would be nice to detect an attempt to use a 64-bit ABI when only 32-bit registers are provided. */ + reg_names = NULL; } /* First of all, extract the elf_flags, if available. */ @@ -6223,66 +6351,19 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_elf_make_msymbol_special (gdbarch, mips_elf_make_msymbol_special); - /* Fill in the OS dependant register numbers and names. */ - { - const char **reg_names; - struct mips_regnum *regnum = GDBARCH_OBSTACK_ZALLOC (gdbarch, - struct mips_regnum); - 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; - regnum->cause = 65; - regnum->badvaddr = 66; - regnum->hi = 67; - regnum->lo = 68; - regnum->fp_control_status = 69; - regnum->fp_implementation_revision = 70; - num_regs = 71; - reg_names = mips_irix_reg_names; - } - else - { - 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 = 90; - if (info.bfd_arch_info != NULL - && info.bfd_arch_info->mach == bfd_mach_mips3900) - reg_names = mips_tx39_reg_names; - else - reg_names = mips_generic_reg_names; - } - /* FIXME: cagney/2003-11-15: For MIPS, hasn't gdbarch_pc_regnum been - replaced by gdbarch_read_pc? */ - set_gdbarch_pc_regnum (gdbarch, regnum->pc + num_regs); - set_gdbarch_sp_regnum (gdbarch, MIPS_SP_REGNUM + num_regs); - set_gdbarch_fp0_regnum (gdbarch, regnum->fp0); - set_gdbarch_num_regs (gdbarch, num_regs); - set_gdbarch_num_pseudo_regs (gdbarch, num_regs); - set_gdbarch_register_name (gdbarch, mips_register_name); - set_gdbarch_virtual_frame_pointer (gdbarch, mips_virtual_frame_pointer); - tdep->mips_processor_reg_names = reg_names; - tdep->regnum = regnum; - } + regnum = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct mips_regnum); + *regnum = mips_regnum; + /* FIXME: cagney/2003-11-15: For MIPS, hasn't gdbarch_pc_regnum been + replaced by gdbarch_read_pc? */ + set_gdbarch_pc_regnum (gdbarch, regnum->pc + num_regs); + set_gdbarch_sp_regnum (gdbarch, MIPS_SP_REGNUM + num_regs); + set_gdbarch_fp0_regnum (gdbarch, regnum->fp0); + set_gdbarch_num_regs (gdbarch, num_regs); + set_gdbarch_num_pseudo_regs (gdbarch, num_regs); + set_gdbarch_register_name (gdbarch, mips_register_name); + set_gdbarch_virtual_frame_pointer (gdbarch, mips_virtual_frame_pointer); + tdep->mips_processor_reg_names = reg_names; + tdep->regnum = regnum; switch (mips_abi) { |