From a4b8ebc89d2cbe6be8b4fe808e0d4c9ac2556a51 Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Sat, 21 Jun 2003 23:14:44 +0000 Subject: [PATCH] 2003-06-21 Andrew Cagney * mips-tdep.c: Include "reggroups.h" and "sim-regno.h". (mips_register_name): Return names for NUM_REGS..2*NUM_REGS instead of 0..NUM_REGS. (mips_register_reggroup_p): New function. (mips_pseudo_register_write): New function. (mips_pseudo_register_read): New function. (mips_register_raw_size): For NUM_REGS..2*NUM_REGS return the size based on the register's type. (read_next_frame_reg): Simplify. Assert that REGNO is a pseudo / cooked. (mips_get_saved_register): Simplify. Assert that REGNO is a pseudo / cooked. (mips_register_byte): New function. Use MIPS_REGISTER_BYTE. (mips_register_type): Replace mips_register_virtual_type. Map NUM_REGS..2*NUM_REGS onto 0..NUM_REGS. Use MIPS_REGISTER_TYPE when available. (read_next_frame_reg): Simplify, but handle SP_REGNUM. Assert that the register is cooked / virtual. (mips_frame_saved_pc): Fetch the cooked PC, and not the raw PC. Only get the extra info when needed. (set_reg_offset): Save the offset in NUM_REGS..2*NUM_REGS as well. (mips32_heuristic_proc_desc): Fetch the cooked register. (heuristic_proc_desc, mips_pop_frame, get_frame_pointer): Ditto. (mips_init_extra_frame_info, get_frame_pointer): Ditto. (mips_print_register): Use gdbarch_register_type, instead of REGISTER_VIRTUAL_TYPE. (print_gp_register_row): Use gdbarch_register_type, instead of REGISTER_VIRTUAL_TYPE. Allow for a pseudo / cooked REGNUM. (mips_print_registers_info): Assert REGNO is pseodo / cooked. Print the pseudo / cooked registers. (mips_print_registers_info): Assert REGNO is pseodo / cooked. Print the pseudo / cooked registers. (mips_xfer_register): Use regcache_cooked_read_part. Assert that REG_NUM is pseudo / cooked. (mips_o32_xfer_return_value): Xfer the pseudo / cooked register. (mips_n32n64_xfer_return_value): Ditto. (mips_stab_reg_to_regnum): Map onto NUM_REGS..2*NUM_REGS. (mips_dwarf_dwarf2_ecoff_reg_to_regnum): Ditto. (mips_register_sim_regno): New function. (mips_gdbarch_init): Set deprecated_register_byte, register_group_p, pseudo_register_write, pseudo_register_read, register_sim_regno, and num_pseudo_regs. Set register_type, instead of register_virtual_type. * Makefile.in (mips-tdep.o): Update dependencies. * config/mips/tm-mips64.h (MIPS_REGISTER_TYPE): Rename REGISTER_VIRTUAL_TYPE. * config/mips/tm-mips.h (MIPS_REGISTER_TYPE): Ditto. * config/mips/tm-irix5.h (MIPS_REGISTER_TYPE): Ditto. * config/mips/tm-mips.h (MIPS_REGISTER_BYTE): Rename REGISTER_BYTE. * config/mips/tm-irix6.h (MIPS_REGISTER_BYTE): Ditto. * config/mips/tm-irix5.h (MIPS_REGISTER_BYTE): Ditto. --- gdb/ChangeLog | 54 ++++++ gdb/Makefile.in | 8 +- gdb/config/mips/tm-irix5.h | 8 +- gdb/config/mips/tm-irix6.h | 6 +- gdb/config/mips/tm-mips.h | 6 +- gdb/config/mips/tm-mips64.h | 2 +- gdb/mips-tdep.c | 464 ++++++++++++++++++++++++++++---------------- 7 files changed, 370 insertions(+), 178 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 624d14f..6b1da44 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,57 @@ +2003-06-21 Andrew Cagney + + * mips-tdep.c: Include "reggroups.h" and "sim-regno.h". + (mips_register_name): Return names for NUM_REGS..2*NUM_REGS + instead of 0..NUM_REGS. + (mips_register_reggroup_p): New function. + (mips_pseudo_register_write): New function. + (mips_pseudo_register_read): New function. + (mips_register_raw_size): For NUM_REGS..2*NUM_REGS return the size + based on the register's type. + (read_next_frame_reg): Simplify. Assert that REGNO is a pseudo / + cooked. + (mips_get_saved_register): Simplify. Assert that REGNO is a + pseudo / cooked. + (mips_register_byte): New function. Use MIPS_REGISTER_BYTE. + (mips_register_type): Replace mips_register_virtual_type. Map + NUM_REGS..2*NUM_REGS onto 0..NUM_REGS. Use MIPS_REGISTER_TYPE + when available. + (read_next_frame_reg): Simplify, but handle SP_REGNUM. Assert + that the register is cooked / virtual. + (mips_frame_saved_pc): Fetch the cooked PC, and not the raw PC. + Only get the extra info when needed. + (set_reg_offset): Save the offset in NUM_REGS..2*NUM_REGS as well. + (mips32_heuristic_proc_desc): Fetch the cooked register. + (heuristic_proc_desc, mips_pop_frame, get_frame_pointer): Ditto. + (mips_init_extra_frame_info, get_frame_pointer): Ditto. + (mips_print_register): Use gdbarch_register_type, instead of + REGISTER_VIRTUAL_TYPE. + (print_gp_register_row): Use gdbarch_register_type, instead of + REGISTER_VIRTUAL_TYPE. Allow for a pseudo / cooked REGNUM. + (mips_print_registers_info): Assert REGNO is pseodo / cooked. + Print the pseudo / cooked registers. + (mips_print_registers_info): Assert REGNO is pseodo / cooked. + Print the pseudo / cooked registers. + (mips_xfer_register): Use regcache_cooked_read_part. Assert that + REG_NUM is pseudo / cooked. + (mips_o32_xfer_return_value): Xfer the pseudo / cooked register. + (mips_n32n64_xfer_return_value): Ditto. + (mips_stab_reg_to_regnum): Map onto NUM_REGS..2*NUM_REGS. + (mips_dwarf_dwarf2_ecoff_reg_to_regnum): Ditto. + (mips_register_sim_regno): New function. + (mips_gdbarch_init): Set deprecated_register_byte, + register_group_p, pseudo_register_write, pseudo_register_read, + register_sim_regno, and num_pseudo_regs. Set register_type, + instead of register_virtual_type. + * Makefile.in (mips-tdep.o): Update dependencies. + * config/mips/tm-mips64.h (MIPS_REGISTER_TYPE): Rename + REGISTER_VIRTUAL_TYPE. + * config/mips/tm-mips.h (MIPS_REGISTER_TYPE): Ditto. + * config/mips/tm-irix5.h (MIPS_REGISTER_TYPE): Ditto. + * config/mips/tm-mips.h (MIPS_REGISTER_BYTE): Rename REGISTER_BYTE. + * config/mips/tm-irix6.h (MIPS_REGISTER_BYTE): Ditto. + * config/mips/tm-irix5.h (MIPS_REGISTER_BYTE): Ditto. + 2003-06-21 Daniel Jacobowitz * Makefile.in (cli-cmds.o): Depend on $(gdb_vfork_h) diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 22c7aa9..28433cd 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -2001,10 +2001,10 @@ mips-linux-tdep.o: mips-linux-tdep.c $(defs_h) $(gdbcore_h) $(target_h) \ mips-nat.o: mips-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(regcache_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) + $(language_h) $(gdbcore_h) $(symfile_h) $(objfiles_h) $(gdbtypes_h) \ + $(target_h) $(arch_utils_h) $(regcache_h) $(osabi_h) $(mips_tdep_h) \ + $(block_h) $(reggroups_h) $(opcode_mips_h) $(elf_mips_h) \ + $(elf_bfd_h) $(symcat_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) diff --git a/gdb/config/mips/tm-irix5.h b/gdb/config/mips/tm-irix5.h index 3d598c9..932852e 100644 --- a/gdb/config/mips/tm-irix5.h +++ b/gdb/config/mips/tm-irix5.h @@ -30,16 +30,16 @@ * Irix 6 (n32 ABI) has 32-bit GP regs and 64-bit FP regs */ -#undef REGISTER_BYTE -#define REGISTER_BYTE(N) \ +#undef MIPS_REGISTER_BYTE +#define MIPS_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) \ +#undef MIPS_REGISTER_TYPE +#define MIPS_REGISTER_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 \ diff --git a/gdb/config/mips/tm-irix6.h b/gdb/config/mips/tm-irix6.h index 14de12e..e6395ae 100644 --- a/gdb/config/mips/tm-irix6.h +++ b/gdb/config/mips/tm-irix6.h @@ -62,8 +62,8 @@ #define FCRIR_REGNUM 70 /* FP implementation/revision */ -#undef REGISTER_BYTE -#define REGISTER_BYTE(N) \ +#undef MIPS_REGISTER_BYTE +#define MIPS_REGISTER_BYTE(N) \ (((N) < FP0_REGNUM) ? (N) * MIPS_REGSIZE : \ ((N) < FP0_REGNUM + 32) ? \ FP0_REGNUM * MIPS_REGSIZE + \ @@ -94,4 +94,4 @@ #define SIGFRAME_REG_SIZE 8 /* Undefine those methods which have been multiarched. */ -#undef REGISTER_VIRTUAL_TYPE +#undef MIPS_REGISTER_TYPE diff --git a/gdb/config/mips/tm-mips.h b/gdb/config/mips/tm-mips.h index 39421fd..51a6a7d 100644 --- a/gdb/config/mips/tm-mips.h +++ b/gdb/config/mips/tm-mips.h @@ -98,13 +98,13 @@ extern int mips_step_skips_delay (CORE_ADDR); /* Index within `registers' of the first byte of the space for register N. */ -#define REGISTER_BYTE(N) ((N) * MIPS_REGSIZE) +#define MIPS_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) \ +#ifndef MIPS_REGISTER_TYPE +#define MIPS_REGISTER_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 \ diff --git a/gdb/config/mips/tm-mips64.h b/gdb/config/mips/tm-mips64.h index 13e62d2..2547e86 100644 --- a/gdb/config/mips/tm-mips64.h +++ b/gdb/config/mips/tm-mips64.h @@ -23,7 +23,7 @@ #define MIPS_REGSIZE 8 /* define 8 byte register type */ -#define REGISTER_VIRTUAL_TYPE(N) \ +#define MIPS_REGISTER_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 \ diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index c5dccc9..4009ca5 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -42,11 +42,12 @@ #include "osabi.h" #include "mips-tdep.h" #include "block.h" - +#include "reggroups.h" #include "opcode/mips.h" #include "elf/mips.h" #include "elf-bfd.h" #include "symcat.h" +#include "sim-regno.h" static void set_reg_offset (CORE_ADDR *saved_regs, int regnum, CORE_ADDR off); @@ -270,6 +271,7 @@ mips_xfer_register (struct regcache *regcache, int reg_num, int length, { bfd_byte reg[MAX_REGISTER_SIZE]; int reg_offset = 0; + gdb_assert (reg_num >= NUM_REGS); /* Need to transfer the left or right part of the register, based on the targets byte order. */ switch (endian) @@ -298,9 +300,9 @@ mips_xfer_register (struct regcache *regcache, int reg_num, int length, fprintf_unfiltered (gdb_stdlog, "%02x", out[buf_offset + i]); } if (in != NULL) - regcache_raw_read_part (regcache, reg_num, reg_offset, length, in + buf_offset); + regcache_cooked_read_part (regcache, reg_num, reg_offset, length, in + buf_offset); if (out != NULL) - regcache_raw_write_part (regcache, reg_num, reg_offset, length, out + buf_offset); + regcache_cooked_write_part (regcache, reg_num, reg_offset, length, out + buf_offset); if (mips_debug && in != NULL) { int i; @@ -440,21 +442,27 @@ mips_register_name (int regno) enum mips_abi abi = mips_abi (current_gdbarch); + /* Map [NUM_REGS .. 2*NUM_REGS) onto the raw registers, but then + don't make the raw register names visible. */ + int rawnum = regno % NUM_REGS; + if (regno < NUM_REGS) + return ""; + /* 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) + if (0 <= rawnum && rawnum < 32) { if (abi == MIPS_ABI_N32 || abi == MIPS_ABI_N64) - return mips_n32_n64_gpr_names[regno]; + return mips_n32_n64_gpr_names[rawnum]; else - return mips_gpr_names[regno]; + return mips_gpr_names[rawnum]; } - else if (32 <= regno && regno < NUM_REGS) - return mips_processor_reg_names[regno - 32]; + else if (32 <= rawnum && rawnum < NUM_REGS) + return mips_processor_reg_names[rawnum - 32]; else internal_error (__FILE__, __LINE__, - "mips_register_name: bad register number %d", regno); + "mips_register_name: bad register number %d", rawnum); } /* *INDENT-OFF* */ @@ -524,8 +532,63 @@ struct { }; /* *INDENT-ON* */ +/* Return the groups that a MIPS register can be categorised into. */ +static int +mips_register_reggroup_p (struct gdbarch *gdbarch, int regnum, + struct reggroup *reggroup) +{ + int vector_p; + int float_p; + int raw_p; + int rawnum = regnum % NUM_REGS; + int pseudo = regnum / NUM_REGS; + if (reggroup == all_reggroup) + return pseudo; + vector_p = TYPE_VECTOR (register_type (gdbarch, regnum)); + float_p = TYPE_CODE (register_type (gdbarch, regnum)) == TYPE_CODE_FLT; + /* FIXME: cagney/2003-04-13: Can't yet use gdbarch_num_regs + (gdbarch), as not all architectures are multi-arch. */ + raw_p = rawnum < NUM_REGS; + if (REGISTER_NAME (regnum) == NULL + || REGISTER_NAME (regnum)[0] == '\0') + return 0; + if (reggroup == float_reggroup) + return float_p && pseudo; + if (reggroup == vector_reggroup) + return vector_p && pseudo; + if (reggroup == general_reggroup) + return (!vector_p && !float_p) && pseudo; + /* Save the pseudo registers. Need to make certain that any code + extracting register values from a saved register cache also uses + pseudo registers. */ + if (reggroup == save_reggroup) + return raw_p && pseudo; + /* Restore the same pseudo register. */ + if (reggroup == restore_reggroup) + return raw_p && pseudo; + return 0; +} + +/* Map the symbol table registers which live in the range [1 * + NUM_REGS .. 2 * NUM_REGS) back onto the corresponding raw + registers. */ +static void +mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, + int cookednum, void *buf) +{ + gdb_assert (cookednum >= NUM_REGS && cookednum < 2 * NUM_REGS); + return regcache_raw_read (regcache, cookednum % NUM_REGS, buf); +} + +static void +mips_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, + int cookednum, const void *buf) +{ + gdb_assert (cookednum >= NUM_REGS && cookednum < 2 * NUM_REGS); + return regcache_raw_write (regcache, cookednum % NUM_REGS, buf); +} /* Table to translate MIPS16 register field to actual register number. */ static int mips16_to_32_reg[8] = @@ -575,22 +638,73 @@ mips_print_extra_frame_info (struct frame_info *fi) /* Number of bytes of storage in the actual machine representation for register N. NOTE: This indirectly defines the register size - transfered by the GDB protocol. */ + transfered by the GDB protocol. */ static int mips64_transfers_32bit_regs_p = 0; static int -mips_register_raw_size (int reg_nr) +mips_register_raw_size (int regnum) { - 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; + gdb_assert (regnum >= 0); + if (regnum < NUM_REGS) + { + /* For compatibility with old code, implemnt the broken register raw + size map for the raw registers. + + NOTE: cagney/2003-06-15: This is so bogus. The register's + raw size is changing according to the ABI + (FP_REGISTER_DOUBLE). Also, GDB's protocol is defined by a + combination of REGISTER_RAW_SIZE and REGISTER_BYTE. */ + if (mips64_transfers_32bit_regs_p) + return REGISTER_VIRTUAL_SIZE (regnum); + else if (regnum >= FP0_REGNUM && regnum < 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; + } + else if (regnum < 2 * NUM_REGS) + { + /* For the moment map [NUM_REGS .. 2*NUM_REGS) onto the same raw + registers, but always return the virtual size. */ + int rawnum = regnum % NUM_REGS; + return TYPE_LENGTH (MIPS_REGISTER_TYPE (rawnum)); + } else - return MIPS_REGSIZE; + internal_error (__FILE__, __LINE__, "Register %d out of range", regnum); +} + +/* Register offset in a buffer for each register. + + FIXME: cagney/2003-06-15: This is so bogus. Instead REGISTER_TYPE + should strictly return the layout of the buffer. Unfortunatly + remote.c and the MIPS have come to rely on a custom layout that + doesn't 1:1 map onto the register type. */ + +static int +mips_register_byte (int regnum) +{ + gdb_assert (regnum >= 0); + if (regnum < NUM_REGS) + /* Pick up the relevant per-tm file register byte method. */ + return MIPS_REGISTER_BYTE (regnum); + else if (regnum < 2 * NUM_REGS) + { + int reg; + int byte; + /* Start with the end of the raw register buffer - assum that + MIPS_REGISTER_BYTE (NUM_REGS) returns that end. */ + byte = MIPS_REGISTER_BYTE (NUM_REGS); + /* Add space for all the proceeding registers based on their + real size. */ + for (reg = NUM_REGS; reg < regnum; reg++) + byte += TYPE_LENGTH (MIPS_REGISTER_TYPE ((reg % NUM_REGS))); + return byte; + } + else + internal_error (__FILE__, __LINE__, "Register %d out of range", regnum); } /* Convert between RAW and VIRTUAL registers. The RAW register size @@ -660,20 +774,20 @@ mips_value_to_register (struct frame_info *frame, int regnum, put_frame_register (frame, regnum + 1, (const char *) from + 0); } -/* 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. */ +/* Return the GDB type object for the "standard" data type of data in + register REG. */ static struct type * -mips_register_virtual_type (int reg) -{ - if (FP0_REGNUM <= reg && reg < FP0_REGNUM + 32) +mips_register_type (struct gdbarch *gdbarch, int regnum) +{ + /* For moment, map [NUM_REGS .. 2*NUM_REGS) onto the same raw + registers. Even return the same type. */ + int rawnum = regnum % NUM_REGS; + gdb_assert (rawnum >= 0 && rawnum < NUM_REGS); +#ifdef MIPS_REGISTER_TYPE + return MIPS_REGISTER_TYPE (rawnum); +#else + if (FP0_REGNUM <= rawnum && rawnum < FP0_REGNUM + 32) { /* Floating point registers... */ if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) @@ -681,9 +795,9 @@ mips_register_virtual_type (int reg) else return builtin_type_ieee_double_little; } - else if (reg == PS_REGNUM /* CR */) + else if (rawnum == PS_REGNUM /* CR */) return builtin_type_uint32; - else if (FCRCS_REGNUM <= reg && reg <= LAST_EMBED_REGNUM) + else if (FCRCS_REGNUM <= rawnum && rawnum <= LAST_EMBED_REGNUM) return builtin_type_uint32; else { @@ -694,6 +808,7 @@ mips_register_virtual_type (int reg) else return builtin_type_uint32; } +#endif } /* TARGET_READ_SP -- Remove useless bits from the stack pointer. */ @@ -1658,37 +1773,23 @@ mips_find_saved_regs (struct frame_info *fci) static CORE_ADDR read_next_frame_reg (struct frame_info *fi, int regno) { - int optimized; - CORE_ADDR addr; - int realnum; - enum lval_type lval; - char raw_buffer[MAX_REGISTER_SIZE]; - + /* Always a pseudo. */ + gdb_assert (regno >= NUM_REGS); if (fi == NULL) { - regcache_cooked_read (current_regcache, regno, raw_buffer); + LONGEST val; + regcache_cooked_read_signed (current_regcache, regno, &val); + return val; } + else if ((regno % NUM_REGS) == SP_REGNUM) + /* The SP_REGNUM is special, its value is stored in saved_regs. + In fact, it is so special that it can even only be fetched + using a raw register number! Once this code as been converted + to frame-unwind the problem goes away. */ + return frame_unwind_register_signed (fi, regno % NUM_REGS); else - { - frame_register_unwind (fi, regno, &optimized, &lval, &addr, &realnum, - raw_buffer); - /* FIXME: cagney/2002-09-13: This is just soooo bad. The MIPS - should have a pseudo register range that correspons to the ABI's, - rather than the ISA's, view of registers. These registers would - then implicitly describe their size and hence could be used - without the below munging. */ - if (lval == lval_memory) - { - if (regno < 32) - { - /* Only MIPS_SAVED_REGSIZE bytes of GP registers are - saved. */ - return read_memory_integer (addr, MIPS_SAVED_REGSIZE); - } - } - } + return frame_unwind_register_signed (fi, regno); - return extract_signed_integer (raw_buffer, REGISTER_VIRTUAL_SIZE (regno)); } /* mips_addr_bits_remove - remove useless address bits */ @@ -1778,23 +1879,29 @@ static CORE_ADDR mips_frame_saved_pc (struct frame_info *frame) { CORE_ADDR saved_pc; - mips_extra_func_info_t proc_desc = get_frame_extra_info (frame)->proc_desc; - /* 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); if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (frame), 0, 0)) { LONGEST tmp; - frame_unwind_signed_register (frame, PC_REGNUM, &tmp); + /* Always unwind the cooked PC register value. */ + frame_unwind_signed_register (frame, NUM_REGS + PC_REGNUM, &tmp); saved_pc = tmp; } - else if (proc_desc && PROC_DESC_IS_DUMMY (proc_desc)) - saved_pc = read_memory_integer (get_frame_base (frame) - MIPS_SAVED_REGSIZE, MIPS_SAVED_REGSIZE); else - saved_pc = read_next_frame_reg (frame, pcreg); - + { + mips_extra_func_info_t proc_desc + = get_frame_extra_info (frame)->proc_desc; + if (proc_desc && PROC_DESC_IS_DUMMY (proc_desc)) + saved_pc = read_memory_integer (get_frame_base (frame) - MIPS_SAVED_REGSIZE, MIPS_SAVED_REGSIZE); + else + { + /* 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); + saved_pc = read_next_frame_reg (frame, NUM_REGS + pcreg); + } + } return ADDR_BITS_REMOVE (saved_pc); } @@ -1810,13 +1917,22 @@ static CORE_ADDR *temp_saved_regs; /* Set a register's saved stack address in temp_saved_regs. If an address has already been set for this register, do nothing; this way we will only recognize the first save of a given register in a - function prologue. */ + function prologue. + + For simplicity, save the address in both [0 .. NUM_REGS) and + [NUM_REGS .. 2*NUM_REGS). Strictly speaking, only the second range + is used as it is only second range (the ABI instead of ISA + registers) that comes into play when finding saved registers in a + frame. */ static void set_reg_offset (CORE_ADDR *saved_regs, int regno, CORE_ADDR offset) { if (saved_regs[regno] == 0) - saved_regs[regno] = offset; + { + saved_regs[regno + 0 * NUM_REGS] = offset; + saved_regs[regno + 1 * NUM_REGS] = offset; + } } @@ -2168,7 +2284,7 @@ restart: { unsigned alloca_adjust; PROC_FRAME_REG (&temp_proc_desc) = 30; - frame_addr = read_next_frame_reg (next_frame, 30); + frame_addr = read_next_frame_reg (next_frame, NUM_REGS + 30); alloca_adjust = (unsigned) (frame_addr - (sp + low_word)); if (alloca_adjust > 0) { @@ -2191,7 +2307,7 @@ restart: { unsigned alloca_adjust; PROC_FRAME_REG (&temp_proc_desc) = 30; - frame_addr = read_next_frame_reg (next_frame, 30); + frame_addr = read_next_frame_reg (next_frame, NUM_REGS + 30); alloca_adjust = (unsigned) (frame_addr - sp); if (alloca_adjust > 0) { @@ -2219,7 +2335,7 @@ heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc, CORE_ADDR sp; if (cur_frame) - sp = read_next_frame_reg (next_frame, SP_REGNUM); + sp = read_next_frame_reg (next_frame, NUM_REGS + SP_REGNUM); else sp = 0; @@ -2492,7 +2608,7 @@ static CORE_ADDR get_frame_pointer (struct frame_info *frame, mips_extra_func_info_t proc_desc) { - return (read_next_frame_reg (frame, PROC_FRAME_REG (proc_desc)) + return (read_next_frame_reg (frame, NUM_REGS + PROC_FRAME_REG (proc_desc)) + PROC_FRAME_OFFSET (proc_desc) - PROC_FRAME_ADJUST (proc_desc)); } @@ -2578,7 +2694,7 @@ mips_init_extra_frame_info (int fromleaf, struct frame_info *fci) 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), NUM_REGS + 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 @@ -4089,10 +4205,11 @@ static void mips_print_register (struct ui_file *file, struct frame_info *frame, int regnum, int all) { + struct gdbarch *gdbarch = get_frame_arch (frame); char raw_buffer[MAX_REGISTER_SIZE]; int offset; - if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT) + if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) == TYPE_CODE_FLT) { mips_print_fp_register (file, frame, regnum); return; @@ -4121,8 +4238,7 @@ mips_print_register (struct ui_file *file, struct frame_info *frame, else offset = 0; - print_scalar_formatted (raw_buffer + offset, - REGISTER_VIRTUAL_TYPE (regnum), + print_scalar_formatted (raw_buffer + offset, gdbarch_register_type (gdbarch, regnum), 'x', 0, file); } @@ -4144,39 +4260,43 @@ print_fp_register_row (struct ui_file *file, struct frame_info *frame, static int print_gp_register_row (struct ui_file *file, struct frame_info *frame, - int regnum) + int start_regnum) { + struct gdbarch *gdbarch = get_frame_arch (frame); /* do values for GP (int) regs */ char raw_buffer[MAX_REGISTER_SIZE]; int ncols = (MIPS_REGSIZE == 8 ? 4 : 8); /* display cols per row */ int col, byte; - int start_regnum = regnum; - int numregs = NUM_REGS; - + int regnum; /* For GP registers, we print a separate row of names above the vals */ fprintf_filtered (file, " "); - for (col = 0; col < ncols && regnum < numregs; regnum++) + for (col = 0, regnum = start_regnum; + col < ncols && regnum < NUM_REGS + NUM_PSEUDO_REGS; + regnum++) { if (*REGISTER_NAME (regnum) == '\0') continue; /* unused register */ - if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT) + if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) == TYPE_CODE_FLT) break; /* end the row: reached FP register */ fprintf_filtered (file, MIPS_REGSIZE == 8 ? "%17s" : "%9s", REGISTER_NAME (regnum)); col++; } + /* print the R0 to R31 names */ fprintf_filtered (file, - start_regnum < MIPS_NUMREGS ? "\n R%-4d" : "\n ", - start_regnum); /* print the R0 to R31 names */ + (start_regnum % NUM_REGS) < MIPS_NUMREGS + ? "\n R%-4d" : "\n ", + start_regnum); - regnum = start_regnum; /* go back to start of row */ /* now print the values in hex, 4 or 8 to the row */ - for (col = 0; col < ncols && regnum < numregs; regnum++) + for (col = 0, regnum = start_regnum; + col < ncols && regnum < NUM_REGS + NUM_PSEUDO_REGS; + regnum++) { if (*REGISTER_NAME (regnum) == '\0') continue; /* unused register */ - if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT) + if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) == TYPE_CODE_FLT) break; /* end row: reached FP register */ /* OK: get the data in raw format. */ if (!frame_register_read (frame, regnum, raw_buffer)) @@ -4212,6 +4332,7 @@ mips_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file, { if (regnum != -1) /* do one specified register */ { + gdb_assert (regnum >= NUM_REGS); if (*(REGISTER_NAME (regnum)) == '\0') error ("Not a valid register for the current processor type"); @@ -4221,10 +4342,10 @@ mips_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file, else /* do all (or most) registers */ { - regnum = 0; - while (regnum < NUM_REGS) + regnum = NUM_REGS; + while (regnum < NUM_REGS + NUM_PSEUDO_REGS) { - if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT) + if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) == TYPE_CODE_FLT) { if (all) /* true for "INFO ALL-REGISTERS" command */ regnum = print_fp_register_row (file, frame, regnum); @@ -4711,30 +4832,30 @@ mips_o32_xfer_return_value (struct type *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, NUM_REGS + FP0_REGNUM, TYPE_LENGTH (type), TARGET_BYTE_ORDER, in, out, 0); } else if (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8 && tdep->mips_fpu_type != MIPS_FPU_NONE) { - /* A double-precision floating-point value. It fits in the - least significant part of FP0/FP1 but with byte ordering - based on the target (???). */ + /* A double-precision floating-point value. The most + significant part goes in FP1, and the least significant in + FP0. */ if (mips_debug) - fprintf_unfiltered (gdb_stderr, "Return float in $fp0/$fp1\n"); + fprintf_unfiltered (gdb_stderr, "Return float in $fp1/$fp0\n"); switch (TARGET_BYTE_ORDER) { case BFD_ENDIAN_LITTLE: - mips_xfer_register (regcache, FP0_REGNUM + 0, 4, + mips_xfer_register (regcache, NUM_REGS + FP0_REGNUM + 0, 4, TARGET_BYTE_ORDER, in, out, 0); - mips_xfer_register (regcache, FP0_REGNUM + 1, 4, + mips_xfer_register (regcache, NUM_REGS + 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, NUM_REGS + FP0_REGNUM + 1, 4, TARGET_BYTE_ORDER, in, out, 0); - mips_xfer_register (regcache, FP0_REGNUM + 0, 4, + mips_xfer_register (regcache, NUM_REGS + FP0_REGNUM + 0, 4, TARGET_BYTE_ORDER, in, out, 4); break; default: @@ -4769,7 +4890,8 @@ mips_o32_xfer_return_value (struct type *type, / TARGET_CHAR_BIT); if (mips_debug) fprintf_unfiltered (gdb_stderr, "Return float struct+%d\n", offset); - mips_xfer_register (regcache, regnum, TYPE_LENGTH (TYPE_FIELD_TYPE (type, field)), + mips_xfer_register (regcache, NUM_REGS + regnum, + TYPE_LENGTH (TYPE_FIELD_TYPE (type, field)), TARGET_BYTE_ORDER, in, out, offset); } } @@ -4793,8 +4915,8 @@ mips_o32_xfer_return_value (struct type *type, if (mips_debug) fprintf_unfiltered (gdb_stderr, "Return struct+%d:%d in $%d\n", offset, xfer, regnum); - mips_xfer_register (regcache, regnum, xfer, BFD_ENDIAN_UNKNOWN, - in, out, offset); + mips_xfer_register (regcache, NUM_REGS + regnum, xfer, + BFD_ENDIAN_UNKNOWN, in, out, offset); } } #endif @@ -4816,8 +4938,8 @@ mips_o32_xfer_return_value (struct type *type, if (mips_debug) fprintf_unfiltered (gdb_stderr, "Return scalar+%d:%d in $%d\n", offset, xfer, regnum); - mips_xfer_register (regcache, regnum, xfer, TARGET_BYTE_ORDER, - in, out, offset); + mips_xfer_register (regcache, NUM_REGS + regnum, xfer, + TARGET_BYTE_ORDER, in, out, offset); } } } @@ -4851,7 +4973,7 @@ mips_n32n64_xfer_return_value (struct type *type, 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, NUM_REGS + FP0_REGNUM, TYPE_LENGTH (type), TARGET_BYTE_ORDER, in, out, 0); } else if (TYPE_CODE (type) == TYPE_CODE_STRUCT @@ -4881,7 +5003,8 @@ mips_n32n64_xfer_return_value (struct type *type, / TARGET_CHAR_BIT); if (mips_debug) fprintf_unfiltered (gdb_stderr, "Return float struct+%d\n", offset); - mips_xfer_register (regcache, regnum, TYPE_LENGTH (TYPE_FIELD_TYPE (type, field)), + mips_xfer_register (regcache, NUM_REGS + regnum, + TYPE_LENGTH (TYPE_FIELD_TYPE (type, field)), TARGET_BYTE_ORDER, in, out, offset); } } @@ -4903,8 +5026,8 @@ mips_n32n64_xfer_return_value (struct type *type, if (mips_debug) fprintf_unfiltered (gdb_stderr, "Return struct+%d:%d in $%d\n", offset, xfer, regnum); - mips_xfer_register (regcache, regnum, xfer, BFD_ENDIAN_UNKNOWN, - in, out, offset); + mips_xfer_register (regcache, NUM_REGS + regnum, xfer, + BFD_ENDIAN_UNKNOWN, in, out, offset); } } else @@ -4924,8 +5047,8 @@ mips_n32n64_xfer_return_value (struct type *type, if (mips_debug) fprintf_unfiltered (gdb_stderr, "Return scalar+%d:%d in $%d\n", offset, xfer, regnum); - mips_xfer_register (regcache, regnum, xfer, TARGET_BYTE_ORDER, - in, out, offset); + mips_xfer_register (regcache, NUM_REGS + regnum, xfer, + TARGET_BYTE_ORDER, in, out, offset); } } } @@ -5448,8 +5571,8 @@ mips_get_saved_register (char *raw_buffer, int optimizedx; int realnumx; - if (!target_has_registers) - error ("No registers."); + /* Always a pseudo. */ + gdb_assert (regnum >= NUM_REGS); /* Make certain that all needed parameters are present. */ if (addrp == NULL) @@ -5458,28 +5581,20 @@ mips_get_saved_register (char *raw_buffer, lvalp = &lvalx; if (optimizedp == NULL) optimizedp = &optimizedx; - frame_register_unwind (deprecated_get_next_frame_hack (frame), - regnum, optimizedp, lvalp, addrp, - &realnumx, raw_buffer); - - /* FIXME: cagney/2002-09-13: This is just so bad. The MIPS should - have a pseudo register range that correspons to the ABI's, rather - than the ISA's, view of registers. These registers would then - implicitly describe their size and hence could be used without - the below munging. */ - if ((*lvalp) == lval_memory) - { - if (raw_buffer != NULL) - { - if (regnum < 32) - { - /* Only MIPS_SAVED_REGSIZE bytes of GP registers are - saved. */ - LONGEST val = read_memory_integer ((*addrp), MIPS_SAVED_REGSIZE); - store_unsigned_integer (raw_buffer, REGISTER_RAW_SIZE (regnum), val); - } - } - } + + if ((regnum % NUM_REGS) == SP_REGNUM) + /* The SP_REGNUM is special, its value is stored in saved_regs. + In fact, it is so special that it can even only be fetched + using a raw register number! Once this code as been converted + to frame-unwind the problem goes away. */ + frame_register_unwind (deprecated_get_next_frame_hack (frame), + regnum % NUM_REGS, optimizedp, lvalp, addrp, + &realnumx, raw_buffer); + else + /* Get it from the next frame. */ + frame_register_unwind (deprecated_get_next_frame_hack (frame), + regnum, optimizedp, lvalp, addrp, + &realnumx, raw_buffer); } /* Immediately after a function call, return the saved pc. @@ -5494,48 +5609,64 @@ mips_saved_pc_after_call (struct frame_info *frame) } -/* Convert a dbx stab register number (from `r' declaration) to a gdb - REGNUM */ +/* Convert a dbx stab register number (from `r' declaration) to a GDB + [1 * NUM_REGS .. 2 * NUM_REGS) REGNUM. */ static int mips_stab_reg_to_regnum (int num) { + int regnum; if (num >= 0 && num < 32) - return num; + regnum = num; else if (num >= 38 && num < 70) - return num + FP0_REGNUM - 38; + regnum = num + FP0_REGNUM - 38; else if (num == 70) - return HI_REGNUM; + regnum = HI_REGNUM; else if (num == 71) - return LO_REGNUM; + regnum = LO_REGNUM; else - { - /* This will hopefully (eventually) provoke a warning. Should - we be calling complaint() here? */ - return NUM_REGS + NUM_PSEUDO_REGS; - } + /* This will hopefully (eventually) provoke a warning. Should + we be calling complaint() here? */ + return NUM_REGS + NUM_PSEUDO_REGS; + return NUM_REGS + regnum; } -/* Convert a dwarf, dwarf2, or ecoff register number to a gdb REGNUM */ +/* Convert a dwarf, dwarf2, or ecoff register number to a GDB [1 * + NUM_REGS .. 2 * NUM_REGS) REGNUM. */ static int mips_dwarf_dwarf2_ecoff_reg_to_regnum (int num) { + int regnum; if (num >= 0 && num < 32) - return num; + regnum = num; else if (num >= 32 && num < 64) - return num + FP0_REGNUM - 32; + regnum = num + FP0_REGNUM - 32; else if (num == 64) - return HI_REGNUM; + regnum = HI_REGNUM; else if (num == 65) - return LO_REGNUM; + regnum = LO_REGNUM; else - { - /* This will hopefully (eventually) provoke a warning. Should - we be calling complaint() here? */ - return NUM_REGS + NUM_PSEUDO_REGS; - } + /* This will hopefully (eventually) provoke a warning. Should we + be calling complaint() here? */ + return NUM_REGS + NUM_PSEUDO_REGS; + return NUM_REGS + regnum; +} + +static int +mips_register_sim_regno (int regnum) +{ + /* Only makes sense to supply raw registers. */ + gdb_assert (regnum >= 0 && regnum < NUM_REGS); + /* FIXME: cagney/2002-05-13: Need to look at the pseudo register to + decide if it is valid. Should instead define a standard sim/gdb + register numbering scheme. */ + if (REGISTER_NAME (NUM_REGS + regnum) != NULL + && REGISTER_NAME (NUM_REGS + regnum)[0] != '\0') + return regnum; + else + return LEGACY_SIM_REGNO_IGNORE; } @@ -5602,6 +5733,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_tdep *tdep; int elf_flags; enum mips_abi mips_abi, found_abi, wanted_abi; + int num_regs; /* Reset the disassembly info, in case it was set to something non-default. */ @@ -5755,16 +5887,23 @@ mips_gdbarch_init (struct gdbarch_info info, set_gdbarch_double_bit (gdbarch, 64); set_gdbarch_long_double_bit (gdbarch, 64); set_gdbarch_deprecated_register_raw_size (gdbarch, mips_register_raw_size); + set_gdbarch_deprecated_register_byte (gdbarch, mips_register_byte); + set_gdbarch_register_reggroup_p (gdbarch, mips_register_reggroup_p); + set_gdbarch_pseudo_register_read (gdbarch, mips_pseudo_register_read); + set_gdbarch_pseudo_register_write (gdbarch, mips_pseudo_register_write); tdep->found_abi = found_abi; tdep->mips_abi = mips_abi; set_gdbarch_elf_make_msymbol_special (gdbarch, mips_elf_make_msymbol_special); + if (info.osabi == GDB_OSABI_IRIX) - set_gdbarch_num_regs (gdbarch, 71); + num_regs = 71; else - set_gdbarch_num_regs (gdbarch, 90); + num_regs = 90; + set_gdbarch_num_regs (gdbarch, num_regs); + set_gdbarch_num_pseudo_regs (gdbarch, num_regs); switch (mips_abi) { @@ -5956,6 +6095,7 @@ mips_gdbarch_init (struct gdbarch_info info, set_gdbarch_ecoff_reg_to_regnum (gdbarch, mips_dwarf_dwarf2_ecoff_reg_to_regnum); set_gdbarch_dwarf_reg_to_regnum (gdbarch, mips_dwarf_dwarf2_ecoff_reg_to_regnum); set_gdbarch_dwarf2_reg_to_regnum (gdbarch, mips_dwarf_dwarf2_ecoff_reg_to_regnum); + set_gdbarch_register_sim_regno (gdbarch, mips_register_sim_regno); /* Initialize a frame */ set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, mips_find_saved_regs); @@ -5992,9 +6132,7 @@ mips_gdbarch_init (struct gdbarch_info info, 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_deprecated_register_virtual_type (gdbarch, mips_register_virtual_type); + set_gdbarch_register_type (gdbarch, mips_register_type); set_gdbarch_print_registers_info (gdbarch, mips_print_registers_info); set_gdbarch_pc_in_sigtramp (gdbarch, mips_pc_in_sigtramp); -- 2.7.4