X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fmips-tdep.c;h=1686ee45433705fb5626be87862cc341e8a7c1e1;hb=114019bb6e6a29549f225b60e1dfda358c605367;hp=30079b58865ab03e1627f269c4be3abf02084ca2;hpb=c2f05ac92e7fe9e3161ae09ea3f9e0937af42abc;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index 30079b5886..1686ee4543 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -1,7 +1,7 @@ /* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger. - Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, + 1997, 1998, 1999, 2000, 2001, 2002 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. @@ -38,12 +38,18 @@ #include "target.h" #include "arch-utils.h" #include "regcache.h" +#include "osabi.h" +#include "mips-tdep.h" #include "opcode/mips.h" #include "elf/mips.h" #include "elf-bfd.h" #include "symcat.h" +/* A useful bit in the CP0 status register (PS_REGNUM). */ +/* This bit is set if we are emulating 32-bit FPRs on a 64-bit chip. */ +#define ST0_FR (1 << 26) + /* The sizes of floating point registers. */ enum @@ -52,17 +58,19 @@ enum MIPS_FPU_DOUBLE_REGSIZE = 8 }; -/* All the possible MIPS ABIs. */ -enum mips_abi - { - MIPS_ABI_UNKNOWN, - MIPS_ABI_N32, - MIPS_ABI_O32, - MIPS_ABI_O64, - MIPS_ABI_EABI32, - MIPS_ABI_EABI64 - }; +static const char *mips_abi_string; + +static const char *mips_abi_strings[] = { + "auto", + "n32", + "o32", + "n64", + "o64", + "eabi32", + "eabi64", + NULL +}; struct frame_extra_info { @@ -101,12 +109,6 @@ enum mips_fpu_type #endif static int mips_fpu_type_auto = 1; static enum mips_fpu_type mips_fpu_type = MIPS_DEFAULT_FPU_TYPE; -#define MIPS_FPU_TYPE mips_fpu_type - -/* Do not use "TARGET_IS_MIPS64" to test the size of floating point registers */ -#ifndef FP_REGISTER_DOUBLE -#define FP_REGISTER_DOUBLE (REGISTER_VIRTUAL_SIZE(FP0_REGNUM) == 8) -#endif static int mips_debug = 0; @@ -115,54 +117,46 @@ struct gdbarch_tdep { /* from the elf header */ int elf_flags; + /* mips options */ enum mips_abi mips_abi; - const char *mips_abi_string; + 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_regs_have_home_p; int mips_default_stack_argsize; int gdb_target_is_mips64; int default_mask_address_p; + + enum gdb_osabi osabi; }; -#if GDB_MULTI_ARCH -#undef MIPS_EABI #define MIPS_EABI (gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI32 \ || gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI64) -#endif -#if GDB_MULTI_ARCH -#undef MIPS_LAST_FP_ARG_REGNUM #define MIPS_LAST_FP_ARG_REGNUM (gdbarch_tdep (current_gdbarch)->mips_last_fp_arg_regnum) -#endif -#if GDB_MULTI_ARCH -#undef MIPS_LAST_ARG_REGNUM #define MIPS_LAST_ARG_REGNUM (gdbarch_tdep (current_gdbarch)->mips_last_arg_regnum) -#endif -#if GDB_MULTI_ARCH -#undef MIPS_FPU_TYPE #define MIPS_FPU_TYPE (gdbarch_tdep (current_gdbarch)->mips_fpu_type) -#endif /* Return the currently configured (or set) saved register size. */ -#if GDB_MULTI_ARCH -#undef MIPS_DEFAULT_SAVED_REGSIZE #define MIPS_DEFAULT_SAVED_REGSIZE (gdbarch_tdep (current_gdbarch)->mips_default_saved_regsize) -#elif !defined (MIPS_DEFAULT_SAVED_REGSIZE) -#define MIPS_DEFAULT_SAVED_REGSIZE MIPS_REGSIZE -#endif static const char *mips_saved_regsize_string = size_auto; #define MIPS_SAVED_REGSIZE (mips_saved_regsize()) +/* Return the MIPS ABI associated with GDBARCH. */ +enum mips_abi +mips_abi (struct gdbarch *gdbarch) +{ + return gdbarch_tdep (gdbarch)->mips_abi; +} + static unsigned int mips_saved_regsize (void) { @@ -174,36 +168,134 @@ mips_saved_regsize (void) return 4; } +/* Functions for setting and testing a bit in a minimal symbol that + marks it as 16-bit function. The MSB of the minimal symbol's + "info" field is used for this purpose. This field is already + being used to store the symbol size, so the assumption is + that the symbol size cannot exceed 2^31. + + ELF_MAKE_MSYMBOL_SPECIAL tests whether an ELF symbol is "special", + i.e. refers to a 16-bit function, and sets a "special" bit in a + minimal symbol to mark it as a 16-bit function + + MSYMBOL_IS_SPECIAL tests the "special" bit in a minimal symbol + MSYMBOL_SIZE returns the size of the minimal symbol, i.e. + the "info" field with the "special" bit masked out */ + +static void +mips_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym) +{ + if (((elf_symbol_type *)(sym))->internal_elf_sym.st_other == STO_MIPS16) + { + MSYMBOL_INFO (msym) = (char *) + (((long) MSYMBOL_INFO (msym)) | 0x80000000); + SYMBOL_VALUE_ADDRESS (msym) |= 1; + } +} + +static int +msymbol_is_special (struct minimal_symbol *msym) +{ + return (((long) MSYMBOL_INFO (msym) & 0x80000000) != 0); +} + +static long +msymbol_size (struct minimal_symbol *msym) +{ + return ((long) MSYMBOL_INFO (msym) & 0x7fffffff); +} + +/* XFER a value from the big/little/left end of the register. + Depending on the size of the value it might occupy the entire + register or just part of it. Make an allowance for this, aligning + things accordingly. */ + +static void +mips_xfer_register (struct regcache *regcache, int reg_num, int length, + enum bfd_endian endian, bfd_byte *in, const bfd_byte *out, + int buf_offset) +{ + bfd_byte *reg = alloca (MAX_REGISTER_RAW_SIZE); + int reg_offset = 0; + /* Need to transfer the left or right part of the register, based on + the targets byte order. */ + switch (endian) + { + case BFD_ENDIAN_BIG: + reg_offset = REGISTER_RAW_SIZE (reg_num) - length; + break; + case BFD_ENDIAN_LITTLE: + reg_offset = 0; + break; + case BFD_ENDIAN_UNKNOWN: /* Indicates no alignment. */ + reg_offset = 0; + break; + default: + internal_error (__FILE__, __LINE__, "bad switch"); + } + if (mips_debug) + fprintf_unfiltered (gdb_stderr, + "xfer $%d, reg offset %d, buf offset %d, length %d, ", + reg_num, reg_offset, buf_offset, length); + if (mips_debug && out != NULL) + { + int i; + fprintf_unfiltered (gdb_stdlog, "out "); + for (i = 0; i < length; i++) + 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); + if (out != NULL) + regcache_raw_write_part (regcache, reg_num, reg_offset, length, out + buf_offset); + if (mips_debug && in != NULL) + { + int i; + fprintf_unfiltered (gdb_stdlog, "in "); + for (i = 0; i < length; i++) + fprintf_unfiltered (gdb_stdlog, "%02x", in[buf_offset + i]); + } + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, "\n"); +} + +/* Determine if a MIPS3 or later cpu is operating in MIPS{1,2} FPU + compatiblity mode. A return value of 1 means that we have + physical 64-bit registers, but should treat them as 32-bit registers. */ + +static int +mips2_fp_compat (void) +{ + /* MIPS1 and MIPS2 have only 32 bit FPRs, and the FR bit is not + meaningful. */ + if (REGISTER_RAW_SIZE (FP0_REGNUM) == 4) + return 0; + +#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 + + return 0; +} + /* 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. */ -#if GDB_MULTI_ARCH -#undef FP_REGISTER_DOUBLE #define FP_REGISTER_DOUBLE (gdbarch_tdep (current_gdbarch)->mips_fp_register_double) -#endif - -/* Does the caller allocate a ``home'' for each register used in the - function call? The N32 ABI and MIPS_EABI do not, the others do. */ - -#if GDB_MULTI_ARCH -#undef MIPS_REGS_HAVE_HOME_P -#define MIPS_REGS_HAVE_HOME_P (gdbarch_tdep (current_gdbarch)->mips_regs_have_home_p) -#elif !defined (MIPS_REGS_HAVE_HOME_P) -#define MIPS_REGS_HAVE_HOME_P (!MIPS_EABI) -#endif /* 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. */ -#if GDB_MULTI_ARCH -#undef MIPS_DEFAULT_STACK_ARGSIZE #define MIPS_DEFAULT_STACK_ARGSIZE (gdbarch_tdep (current_gdbarch)->mips_default_stack_argsize) -#elif !defined (MIPS_DEFAULT_STACK_ARGSIZE) -#define MIPS_DEFAULT_STACK_ARGSIZE (MIPS_DEFAULT_SAVED_REGSIZE) -#endif #define MIPS_STACK_ARGSIZE (mips_stack_argsize ()) @@ -220,17 +312,9 @@ mips_stack_argsize (void) return 4; } -#if GDB_MULTI_ARCH -#undef GDB_TARGET_IS_MIPS64 #define GDB_TARGET_IS_MIPS64 (gdbarch_tdep (current_gdbarch)->gdb_target_is_mips64 + 0) -#endif -#if GDB_MULTI_ARCH -#undef MIPS_DEFAULT_MASK_ADDRESS_P #define MIPS_DEFAULT_MASK_ADDRESS_P (gdbarch_tdep (current_gdbarch)->default_mask_address_p) -#elif !defined (MIPS_DEFAULT_MASK_ADDRESS_P) -#define MIPS_DEFAULT_MASK_ADDRESS_P (0) -#endif #define VM_MIN_ADDRESS (CORE_ADDR)0x400000 @@ -245,7 +329,7 @@ static CORE_ADDR heuristic_proc_start (CORE_ADDR); static CORE_ADDR read_next_frame_reg (struct frame_info *, int); -int mips_set_processor_type (char *); +static int mips_set_processor_type (char *); static void mips_show_processor_type_command (char *, int); @@ -257,6 +341,12 @@ find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame, int cur_frame); static CORE_ADDR after_prologue (CORE_ADDR pc, mips_extra_func_info_t proc_desc); +static void mips_read_fp_register_single (int regno, char *rare_buffer); +static void mips_read_fp_register_double (int regno, char *rare_buffer); + +static struct type *mips_float_register_type (void); +static struct type *mips_double_register_type (void); + /* This value is the model of MIPS in use. It is derived from the value of the PrID register. */ @@ -275,7 +365,7 @@ static struct cmd_list_element *showmipscmdlist = NULL; char *mips_generic_reg_names[] = MIPS_REGISTER_NAMES; char **mips_processor_reg_names = mips_generic_reg_names; -char * +static const char * mips_register_name (int i) { return mips_processor_reg_names[i]; @@ -293,7 +383,7 @@ char *mips_r3041_reg_names[] = { "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", "",/*"fp"*/ "", "", "", "bus", "ccfg", "", "", "", "", "", "", "port", "cmp", "", "", "epc", "prid", }; @@ -310,7 +400,7 @@ char *mips_r3051_reg_names[] = { "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", ""/*"fp"*/, "", "inx", "rand", "elo", "", "ctxt", "", "", "", "", "", "ehi", "", "", "", "epc", "prid", }; @@ -327,7 +417,7 @@ char *mips_r3081_reg_names[] = { "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", ""/*"fp"*/, "", "inx", "rand", "elo", "cfg", "ctxt", "", "", "", "", "", "ehi", "", "", "", "epc", "prid", }; @@ -386,6 +476,8 @@ static unsigned int heuristic_fence_post = 0; #define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset) #define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset) #define PROC_PC_REG(proc) ((proc)->pdr.pcreg) +/* FIXME drow/2002-06-10: If a pointer on the host is bigger than a long, + this will corrupt pdr.iline. Fortunately we don't use it. */ #define PROC_SYMBOL(proc) (*(struct symbol**)&(proc)->pdr.isym) #define _PROC_MAGIC_ 0x0F0F0F0F #define PROC_DESC_IS_DUMMY(proc) ((proc)->pdr.isym == _PROC_MAGIC_) @@ -416,7 +508,7 @@ mips_print_extra_frame_info (struct frame_info *fi) static int mips64_transfers_32bit_regs_p = 0; -int +static int mips_register_raw_size (int reg_nr) { if (mips64_transfers_32bit_regs_p) @@ -433,7 +525,7 @@ mips_register_raw_size (int reg_nr) /* Convert between RAW and VIRTUAL registers. The RAW register size defines the remote-gdb packet. */ -int +static int mips_register_convertible (int reg_nr) { if (mips64_transfers_32bit_regs_p) @@ -442,7 +534,7 @@ mips_register_convertible (int reg_nr) return (REGISTER_RAW_SIZE (reg_nr) > REGISTER_VIRTUAL_SIZE (reg_nr)); } -void +static void mips_register_convert_to_virtual (int n, struct type *virtual_type, char *raw_buf, char *virt_buf) { @@ -456,7 +548,7 @@ mips_register_convert_to_virtual (int n, struct type *virtual_type, TYPE_LENGTH (virtual_type)); } -void +static void mips_register_convert_to_raw (struct type *virtual_type, int n, char *virt_buf, char *raw_buf) { @@ -471,40 +563,116 @@ mips_register_convert_to_raw (struct type *virtual_type, int n, 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 FP_REGNUM is in this range, and I doubt + that this code is correct for the 64-bit case. */ + +static struct type * +mips_register_virtual_type (int reg) +{ + if (FP0_REGNUM <= reg && reg < FP0_REGNUM + 32) + { + /* Floating point registers... */ + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + return builtin_type_ieee_double_big; + else + return builtin_type_ieee_double_little; + } + 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 + return builtin_type_uint32; + } +} + +/* TARGET_READ_SP -- Remove useless bits from the stack pointer. */ + +static CORE_ADDR +mips_read_sp (void) +{ + return ADDR_BITS_REMOVE (read_register (SP_REGNUM)); +} + /* Should the upper word of 64-bit addresses be zeroed? */ -enum cmd_auto_boolean mask_address_var = CMD_AUTO_BOOLEAN_AUTO; +enum auto_boolean mask_address_var = AUTO_BOOLEAN_AUTO; static int mips_mask_address_p (void) { switch (mask_address_var) { - case CMD_AUTO_BOOLEAN_TRUE: + case AUTO_BOOLEAN_TRUE: return 1; - case CMD_AUTO_BOOLEAN_FALSE: + case AUTO_BOOLEAN_FALSE: return 0; break; - case CMD_AUTO_BOOLEAN_AUTO: + case AUTO_BOOLEAN_AUTO: return MIPS_DEFAULT_MASK_ADDRESS_P; default: internal_error (__FILE__, __LINE__, "mips_mask_address_p: bad switch"); return -1; - } + } } static void -show_mask_address (char *cmd, int from_tty) +show_mask_address (char *cmd, int from_tty, struct cmd_list_element *c) { switch (mask_address_var) { - case CMD_AUTO_BOOLEAN_TRUE: + case AUTO_BOOLEAN_TRUE: printf_filtered ("The 32 bit mips address mask is enabled\n"); break; - case CMD_AUTO_BOOLEAN_FALSE: + case AUTO_BOOLEAN_FALSE: printf_filtered ("The 32 bit mips address mask is disabled\n"); break; - case CMD_AUTO_BOOLEAN_AUTO: + case AUTO_BOOLEAN_AUTO: printf_filtered ("The 32 bit address mask is set automatically. Currently %s\n", mips_mask_address_p () ? "enabled" : "disabled"); break; @@ -512,17 +680,55 @@ show_mask_address (char *cmd, int from_tty) internal_error (__FILE__, __LINE__, "show_mask_address: bad switch"); break; - } + } } /* Should call_function allocate stack space for a struct return? */ -int -mips_use_struct_convention (int gcc_p, struct type *type) + +static int +mips_eabi_use_struct_convention (int gcc_p, struct type *type) { - if (MIPS_EABI) - return (TYPE_LENGTH (type) > 2 * MIPS_SAVED_REGSIZE); - else - return 1; /* Structures are returned by ref in extra arg0 */ + return (TYPE_LENGTH (type) > 2 * MIPS_SAVED_REGSIZE); +} + +static int +mips_n32n64_use_struct_convention (int gcc_p, struct type *type) +{ + return (TYPE_LENGTH (type) > 2 * MIPS_SAVED_REGSIZE); +} + +static int +mips_o32_use_struct_convention (int gcc_p, struct type *type) +{ + return 1; /* Structures are returned by ref in extra arg0. */ +} + +/* Should call_function pass struct by reference? + For each architecture, structs are passed either by + value or by reference, depending on their size. */ + +static int +mips_eabi_reg_struct_has_addr (int gcc_p, struct type *type) +{ + enum type_code typecode = TYPE_CODE (check_typedef (type)); + int len = TYPE_LENGTH (check_typedef (type)); + + if (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION) + return (len > MIPS_SAVED_REGSIZE); + + return 0; +} + +static int +mips_n32n64_reg_struct_has_addr (int gcc_p, struct type *type) +{ + return 0; /* Assumption: N32/N64 never passes struct by ref. */ +} + +static int +mips_o32_reg_struct_has_addr (int gcc_p, struct type *type) +{ + return 0; /* Assumption: O32/O64 never passes struct by ref. */ } /* Tell if the program counter value in MEMADDR is in a MIPS16 function. */ @@ -541,7 +747,7 @@ pc_is_mips16 (bfd_vma memaddr) MIPS16 or normal MIPS. */ sym = lookup_minimal_symbol_by_pc (memaddr); if (sym) - return MSYMBOL_IS_SPECIAL (sym); + return msymbol_is_special (sym); else return 0; } @@ -709,7 +915,7 @@ mips32_relative_offset (unsigned long inst) /* Determine whate to set a single step breakpoint while considering branch prediction */ -CORE_ADDR +static CORE_ADDR mips32_next_pc (CORE_ADDR pc) { unsigned long inst; @@ -1025,7 +1231,6 @@ static CORE_ADDR add_offset_16 (CORE_ADDR pc, int offset) { return ((offset << 2) | ((pc + 2) & (0xf0000000))); - } static CORE_ADDR @@ -1149,7 +1354,7 @@ extended_mips16_next_pc (CORE_ADDR pc, return pc; } -CORE_ADDR +static CORE_ADDR mips16_next_pc (CORE_ADDR pc) { unsigned int insn = fetch_mips_16 (pc); @@ -1171,9 +1376,17 @@ mips_next_pc (CORE_ADDR pc) } /* Guaranteed to set fci->saved_regs to some values (it never leaves it - NULL). */ + NULL). -void + Note: kevinb/2002-08-09: The only caller of this function is (and + should remain) mips_frame_init_saved_regs(). In fact, + aside from calling mips_find_saved_regs(), mips_frame_init_saved_regs() + does nothing more than set frame->saved_regs[SP_REGNUM]. These two + functions should really be combined and now that there is only one + caller, it should be straightforward. (Watch out for multiple returns + though.) */ + +static void mips_find_saved_regs (struct frame_info *fci) { int ireg; @@ -1205,7 +1418,7 @@ mips_find_saved_regs (struct frame_info *fci) /* FIXME! Is this correct?? */ #define SIGFRAME_REG_SIZE MIPS_REGSIZE #endif - if (fci->signal_handler_caller) + if ((get_frame_type (fci) == SIGTRAMP_FRAME)) { for (ireg = 0; ireg < MIPS_NUMREGS; ireg++) { @@ -1238,7 +1451,7 @@ mips_find_saved_regs (struct frame_info *fci) a signal, we assume that all registers have been saved. This assumes that all register saves in a function happen before the first function call. */ - (fci->next == NULL || fci->next->signal_handler_caller) + (fci->next == NULL || (get_frame_type (fci->next) == SIGTRAMP_FRAME)) /* In a dummy frame we know exactly where things are saved. */ && !PROC_DESC_IS_DUMMY (proc_desc) @@ -1323,9 +1536,20 @@ mips_find_saved_regs (struct frame_info *fci) were saved. */ reg_position = fci->frame + PROC_FREG_OFFSET (proc_desc); - /* The freg_offset points to where the first *double* register - is saved. So skip to the high-order word. */ - if (!GDB_TARGET_IS_MIPS64) + /* Apparently, the freg_offset gives the offset to the first 64 bit + saved. + + When the ABI specifies 64 bit saved registers, the FREG_OFFSET + designates the first saved 64 bit register. + + When the ABI specifies 32 bit saved registers, the ``64 bit saved + DOUBLE'' consists of two adjacent 32 bit registers, Hence + FREG_OFFSET, designates the address of the lower register of the + register pair. Adjust the offset so that it designates the upper + register of the pair -- i.e., the address of the first saved 32 + bit register. */ + + if (MIPS_SAVED_REGSIZE == 4) reg_position += MIPS_SAVED_REGSIZE; /* Fill in the offsets for the float registers which float_mask says @@ -1340,24 +1564,49 @@ mips_find_saved_regs (struct frame_info *fci) fci->saved_regs[PC_REGNUM] = fci->saved_regs[RA_REGNUM]; } +/* Set up the 'saved_regs' array. This is a data structure containing + the addresses on the stack where each register has been saved, for + each stack frame. Registers that have not been saved will have + zero here. The stack pointer register is special: rather than the + address where the stack register has been saved, saved_regs[SP_REGNUM] + will have the actual value of the previous frame's stack register. */ + +static void +mips_frame_init_saved_regs (struct frame_info *frame) +{ + if (frame->saved_regs == NULL) + { + mips_find_saved_regs (frame); + } + frame->saved_regs[SP_REGNUM] = frame->frame; +} + static CORE_ADDR read_next_frame_reg (struct frame_info *fi, int regno) { - for (; fi; fi = fi->next) + int optimized; + CORE_ADDR addr; + int realnum; + enum lval_type lval; + void *raw_buffer = alloca (MAX_REGISTER_RAW_SIZE); + 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) { - /* We have to get the saved sp from the sigcontext - if it is a signal handler frame. */ - if (regno == SP_REGNUM && !fi->signal_handler_caller) - return fi->frame; - else + if (regno < 32) { - if (fi->saved_regs == NULL) - mips_find_saved_regs (fi); - if (fi->saved_regs[regno]) - return read_memory_integer (ADDR_BITS_REMOVE (fi->saved_regs[regno]), MIPS_SAVED_REGSIZE); + /* Only MIPS_SAVED_REGSIZE bytes of GP registers are + saved. */ + return read_memory_integer (addr, MIPS_SAVED_REGSIZE); } } - return read_signed_register (regno); + + return extract_signed_integer (raw_buffer, REGISTER_VIRTUAL_SIZE (regno)); } /* mips_addr_bits_remove - remove useless address bits */ @@ -1403,7 +1652,7 @@ mips_addr_bits_remove (CORE_ADDR addr) /* mips_software_single_step() is called just before we want to resume the inferior, if we want to single-step it but there is no hardware - or kernel single-step support (MIPS on Linux for example). We find + or kernel single-step support (MIPS on GNU/Linux for example). We find the target of the coming instruction and breakpoint it. single_step is also called just after the inferior stops. If we had @@ -1428,29 +1677,35 @@ mips_software_single_step (enum target_signal sig, int insert_breakpoints_p) target_remove_breakpoint (next_pc, break_mem); } -static void +static CORE_ADDR mips_init_frame_pc_first (int fromleaf, struct frame_info *prev) { CORE_ADDR pc, tmp; pc = ((fromleaf) ? SAVED_PC_AFTER_CALL (prev->next) : prev->next ? FRAME_SAVED_PC (prev->next) : read_pc ()); - tmp = mips_skip_stub (pc); - prev->pc = tmp ? tmp : pc; + tmp = SKIP_TRAMPOLINE_CODE (pc); + return tmp ? tmp : pc; } -CORE_ADDR +static CORE_ADDR mips_frame_saved_pc (struct frame_info *frame) { CORE_ADDR saved_pc; mips_extra_func_info_t proc_desc = frame->extra_info->proc_desc; /* We have to get the saved pc from the sigcontext if it is a signal handler frame. */ - int pcreg = frame->signal_handler_caller ? PC_REGNUM + int pcreg = (get_frame_type (frame) == SIGTRAMP_FRAME) ? PC_REGNUM : (proc_desc ? PROC_PC_REG (proc_desc) : RA_REGNUM); - if (proc_desc && PROC_DESC_IS_DUMMY (proc_desc)) + if (DEPRECATED_PC_IN_CALL_DUMMY (frame->pc, 0, 0)) + { + LONGEST tmp; + frame_unwind_signed_register (frame, PC_REGNUM, &tmp); + saved_pc = tmp; + } + else if (proc_desc && PROC_DESC_IS_DUMMY (proc_desc)) saved_pc = read_memory_integer (frame->frame - MIPS_SAVED_REGSIZE, MIPS_SAVED_REGSIZE); else saved_pc = read_next_frame_reg (frame, pcreg); @@ -1459,7 +1714,13 @@ mips_frame_saved_pc (struct frame_info *frame) } static struct mips_extra_func_info temp_proc_desc; -static CORE_ADDR temp_saved_regs[NUM_REGS]; + +/* This hack will go away once the get_prev_frame() code has been + modified to set the frame's type first. That is BEFORE init extra + frame info et.al. is called. This is because it will become + possible to skip the init extra info call for sigtramp and dummy + frames. */ +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 @@ -1771,6 +2032,7 @@ mips32_heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc, CORE_ADDR cur_pc; CORE_ADDR frame_addr = 0; /* Value of $r30. Used by gcc for frame-pointer */ restart: + temp_saved_regs = xrealloc (temp_saved_regs, SIZEOF_FRAME_SAVED_REGS); memset (temp_saved_regs, '\0', SIZEOF_FRAME_SAVED_REGS); PROC_FRAME_OFFSET (&temp_proc_desc) = 0; PROC_FRAME_ADJUST (&temp_proc_desc) = 0; /* offset of FP from SP */ @@ -1879,7 +2141,8 @@ heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc, if (start_pc == 0) return NULL; memset (&temp_proc_desc, '\0', sizeof (temp_proc_desc)); - memset (&temp_saved_regs, '\0', SIZEOF_FRAME_SAVED_REGS); + 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; @@ -1893,6 +2156,30 @@ heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc, return &temp_proc_desc; } +struct mips_objfile_private +{ + bfd_size_type size; + char *contents; +}; + +/* Global used to communicate between non_heuristic_proc_desc and + compare_pdr_entries within qsort (). */ +static bfd *the_bfd; + +static int +compare_pdr_entries (const void *a, const void *b) +{ + CORE_ADDR lhs = bfd_get_32 (the_bfd, (bfd_byte *) a); + CORE_ADDR rhs = bfd_get_32 (the_bfd, (bfd_byte *) b); + + if (lhs < rhs) + return -1; + else if (lhs == rhs) + return 0; + else + return 1; +} + static mips_extra_func_info_t non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr) { @@ -1900,23 +2187,145 @@ non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr) mips_extra_func_info_t proc_desc; struct block *b = block_for_pc (pc); struct symbol *sym; + struct obj_section *sec; + struct mips_objfile_private *priv; + + if (DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0)) + return NULL; find_pc_partial_function (pc, NULL, &startaddr, NULL); if (addrptr) *addrptr = startaddr; - if (b == NULL || PC_IN_CALL_DUMMY (pc, 0, 0)) - sym = NULL; - else + + priv = NULL; + + sec = find_pc_section (pc); + if (sec != NULL) { - if (startaddr > BLOCK_START (b)) - /* This is the "pathological" case referred to in a comment in - print_frame_info. It might be better to move this check into - symbol reading. */ - sym = NULL; - else - sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE, 0, NULL); + priv = (struct mips_objfile_private *) sec->objfile->obj_private; + + /* Search the ".pdr" section generated by GAS. This includes most of + the information normally found in ECOFF PDRs. */ + + the_bfd = sec->objfile->obfd; + if (priv == NULL + && (the_bfd->format == bfd_object + && bfd_get_flavour (the_bfd) == bfd_target_elf_flavour + && elf_elfheader (the_bfd)->e_ident[EI_CLASS] == ELFCLASS64)) + { + /* Right now GAS only outputs the address as a four-byte sequence. + This means that we should not bother with this method on 64-bit + targets (until that is fixed). */ + + priv = obstack_alloc (& sec->objfile->psymbol_obstack, + sizeof (struct mips_objfile_private)); + priv->size = 0; + sec->objfile->obj_private = priv; + } + else if (priv == NULL) + { + asection *bfdsec; + + priv = obstack_alloc (& sec->objfile->psymbol_obstack, + sizeof (struct mips_objfile_private)); + + bfdsec = bfd_get_section_by_name (sec->objfile->obfd, ".pdr"); + if (bfdsec != NULL) + { + priv->size = bfd_section_size (sec->objfile->obfd, bfdsec); + priv->contents = obstack_alloc (& sec->objfile->psymbol_obstack, + priv->size); + bfd_get_section_contents (sec->objfile->obfd, bfdsec, + priv->contents, 0, priv->size); + + /* In general, the .pdr section is sorted. However, in the + presence of multiple code sections (and other corner cases) + it can become unsorted. Sort it so that we can use a faster + binary search. */ + qsort (priv->contents, priv->size / 32, 32, compare_pdr_entries); + } + else + priv->size = 0; + + sec->objfile->obj_private = priv; + } + the_bfd = NULL; + + if (priv->size != 0) + { + int low, mid, high; + char *ptr; + + low = 0; + high = priv->size / 32; + + do + { + CORE_ADDR pdr_pc; + + mid = (low + high) / 2; + + ptr = priv->contents + mid * 32; + pdr_pc = bfd_get_signed_32 (sec->objfile->obfd, ptr); + pdr_pc += ANOFFSET (sec->objfile->section_offsets, + SECT_OFF_TEXT (sec->objfile)); + if (pdr_pc == startaddr) + break; + if (pdr_pc > startaddr) + high = mid; + else + low = mid + 1; + } + while (low != high); + + if (low != high) + { + struct symbol *sym = find_pc_function (pc); + + /* Fill in what we need of the proc_desc. */ + proc_desc = (mips_extra_func_info_t) + obstack_alloc (&sec->objfile->psymbol_obstack, + sizeof (struct mips_extra_func_info)); + PROC_LOW_ADDR (proc_desc) = startaddr; + + /* Only used for dummy frames. */ + PROC_HIGH_ADDR (proc_desc) = 0; + + PROC_FRAME_OFFSET (proc_desc) + = bfd_get_32 (sec->objfile->obfd, ptr + 20); + PROC_FRAME_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd, + ptr + 24); + PROC_FRAME_ADJUST (proc_desc) = 0; + PROC_REG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd, + ptr + 4); + PROC_FREG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd, + ptr + 12); + PROC_REG_OFFSET (proc_desc) = bfd_get_32 (sec->objfile->obfd, + ptr + 8); + PROC_FREG_OFFSET (proc_desc) + = bfd_get_32 (sec->objfile->obfd, ptr + 16); + PROC_PC_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd, + ptr + 28); + proc_desc->pdr.isym = (long) sym; + + return proc_desc; + } + } + } + + if (b == NULL) + return NULL; + + if (startaddr > BLOCK_START (b)) + { + /* This is the "pathological" case referred to in a comment in + print_frame_info. It might be better to move this check into + symbol reading. */ + return NULL; } + sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE, 0, NULL); + /* If we never found a PDR for this function in symbol reading, then examine prologues to find the information. */ if (sym) @@ -1936,7 +2345,7 @@ static mips_extra_func_info_t find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame, int cur_frame) { mips_extra_func_info_t proc_desc; - CORE_ADDR startaddr; + CORE_ADDR startaddr = 0; proc_desc = non_heuristic_proc_desc (pc, &startaddr); @@ -1952,7 +2361,7 @@ find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame, int cur_frame) { struct symtab_and_line val; struct symbol *proc_symbol = - PROC_DESC_IS_DUMMY (proc_desc) ? 0 : PROC_SYMBOL (proc_desc); + PROC_DESC_IS_DUMMY (proc_desc) ? 0 : PROC_SYMBOL (proc_desc); if (proc_symbol) { @@ -1964,8 +2373,8 @@ find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame, int cur_frame) if (!proc_symbol || pc < val.pc) { mips_extra_func_info_t found_heuristic = - heuristic_proc_desc (PROC_LOW_ADDR (proc_desc), - pc, next_frame, cur_frame); + heuristic_proc_desc (PROC_LOW_ADDR (proc_desc), + pc, next_frame, cur_frame); if (found_heuristic) proc_desc = found_heuristic; } @@ -1998,14 +2407,15 @@ static CORE_ADDR get_frame_pointer (struct frame_info *frame, mips_extra_func_info_t proc_desc) { - return ADDR_BITS_REMOVE ( - read_next_frame_reg (frame, PROC_FRAME_REG (proc_desc)) + - PROC_FRAME_OFFSET (proc_desc) - PROC_FRAME_ADJUST (proc_desc)); + return ADDR_BITS_REMOVE (read_next_frame_reg (frame, + PROC_FRAME_REG (proc_desc)) + + PROC_FRAME_OFFSET (proc_desc) - + PROC_FRAME_ADJUST (proc_desc)); } -mips_extra_func_info_t cached_proc_desc; +static mips_extra_func_info_t cached_proc_desc; -CORE_ADDR +static CORE_ADDR mips_frame_chain (struct frame_info *frame) { mips_extra_func_info_t proc_desc; @@ -2017,9 +2427,17 @@ mips_frame_chain (struct frame_info *frame) /* Check if the PC is inside a call stub. If it is, fetch the PC of the caller of that stub. */ - if ((tmp = mips_skip_stub (saved_pc)) != 0) + if ((tmp = SKIP_TRAMPOLINE_CODE (saved_pc)) != 0) saved_pc = tmp; + if (DEPRECATED_PC_IN_CALL_DUMMY (saved_pc, 0, 0)) + { + /* A dummy frame, uses SP not FP. Get the old SP value. If all + is well, frame->frame the bottom of the current frame will + contain that value. */ + return frame->frame; + } + /* Look up the procedure descriptor for this PC. */ proc_desc = find_proc_desc (saved_pc, frame, 1); if (!proc_desc) @@ -2032,22 +2450,25 @@ mips_frame_chain (struct frame_info *frame) we loop forever if we see a zero size frame. */ if (PROC_FRAME_REG (proc_desc) == SP_REGNUM && PROC_FRAME_OFFSET (proc_desc) == 0 - /* The previous frame from a sigtramp frame might be frameless - and have frame size zero. */ - && !frame->signal_handler_caller) + /* The previous frame from a sigtramp frame might be frameless + and have frame size zero. */ + && !(get_frame_type (frame) == SIGTRAMP_FRAME) + /* For a generic dummy frame, let get_frame_pointer() unwind a + register value saved as part of the dummy frame call. */ + && !(DEPRECATED_PC_IN_CALL_DUMMY (frame->pc, 0, 0))) return 0; else return get_frame_pointer (frame, proc_desc); } -void +static void mips_init_extra_frame_info (int fromleaf, struct frame_info *fci) { int regnum; /* Use proc_desc calculated in frame_chain */ mips_extra_func_info_t proc_desc = - fci->next ? cached_proc_desc : find_proc_desc (fci->pc, fci->next, 1); + fci->next ? cached_proc_desc : find_proc_desc (fci->pc, fci->next, 1); fci->extra_info = (struct frame_extra_info *) frame_obstack_alloc (sizeof (struct frame_extra_info)); @@ -2064,6 +2485,14 @@ mips_init_extra_frame_info (int fromleaf, struct frame_info *fci) if (fci->pc == PROC_LOW_ADDR (proc_desc) && !PROC_DESC_IS_DUMMY (proc_desc)) fci->frame = read_next_frame_reg (fci->next, SP_REGNUM); + else if (DEPRECATED_PC_IN_CALL_DUMMY (fci->pc, 0, 0)) + /* Do not ``fix'' fci->frame. It will have the value of the + generic dummy frame's top-of-stack (since the draft + fci->frame is obtained by returning the unwound stack + pointer) and that is what we want. That way the fci->frame + value will match the top-of-stack value that was saved as + part of the dummy frames data. */ + /* Do nothing. */; else fci->frame = get_frame_pointer (fci->next, proc_desc); @@ -2072,16 +2501,26 @@ mips_init_extra_frame_info (int fromleaf, struct frame_info *fci) char *name; /* Do not set the saved registers for a sigtramp frame, - mips_find_saved_registers will do that for us. - We can't use fci->signal_handler_caller, it is not yet set. */ + mips_find_saved_registers will do that for us. We can't + use (get_frame_type (fci) == SIGTRAMP_FRAME), it is not + yet set. */ + /* FIXME: cagney/2002-11-18: This problem will go away once + frame.c:get_prev_frame() is modified to set the frame's + type before calling functions like this. */ find_pc_partial_function (fci->pc, &name, (CORE_ADDR *) NULL, (CORE_ADDR *) NULL); - if (!IN_SIGTRAMP (fci->pc, name)) + if (!PC_IN_SIGTRAMP (fci->pc, name)) { frame_saved_regs_zalloc (fci); memcpy (fci->saved_regs, temp_saved_regs, SIZEOF_FRAME_SAVED_REGS); fci->saved_regs[PC_REGNUM] = fci->saved_regs[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. */ + fci->saved_regs[SP_REGNUM] = fci->frame; } } @@ -2103,7 +2542,7 @@ mips_init_extra_frame_info (int fromleaf, struct frame_info *fci) we basically have to look at symbol information for the function that we stopped in, which tells us *which* register (if any) is the base of the frame pointer, and what offset from that register - the frame itself is at. + the frame itself is at. This presents a problem when trying to examine a stack in memory (that isn't executing at the moment), using the "frame" command. We @@ -2137,7 +2576,7 @@ fp_register_arg_p (enum type_code typecode, struct type *arg_type) && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION) && TYPE_NFIELDS (arg_type) == 1 && TYPE_CODE (TYPE_FIELD_TYPE (arg_type, 0)) == TYPE_CODE_FLT)) - && MIPS_FPU_TYPE != MIPS_FPU_NONE); + && MIPS_FPU_TYPE != MIPS_FPU_NONE); } /* On o32, argument passing in GPRs depends on the alignment of the type being @@ -2147,7 +2586,7 @@ static int mips_type_needs_double_align (struct type *type) { enum type_code typecode = TYPE_CODE (type); - + if (typecode == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8) return 1; else if (typecode == TYPE_CODE_STRUCT) @@ -2158,7 +2597,7 @@ mips_type_needs_double_align (struct type *type) } else if (typecode == TYPE_CODE_UNION) { - int i, n; + int i, n; n = TYPE_NFIELDS (type); for (i = 0; i < n; i++) @@ -2169,12 +2608,26 @@ mips_type_needs_double_align (struct type *type) return 0; } -CORE_ADDR -mips_push_arguments (int nargs, - struct value **args, - CORE_ADDR sp, - int struct_return, - CORE_ADDR struct_addr) +/* Macros to round N up or down to the next A boundary; + A must be a power of two. */ + +#define ROUND_DOWN(n,a) ((n) & ~((a)-1)) +#define ROUND_UP(n,a) (((n)+(a)-1) & ~((a)-1)) + +/* Adjust the address downward (direction of stack growth) so that it + is correctly aligned for a new stack frame. */ +static CORE_ADDR +mips_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr) +{ + return ROUND_DOWN (addr, 16); +} + +static CORE_ADDR +mips_eabi_push_arguments (int nargs, + struct value **args, + CORE_ADDR sp, + int struct_return, + CORE_ADDR struct_addr) { int argreg; int float_argreg; @@ -2182,44 +2635,40 @@ mips_push_arguments (int nargs, int len = 0; int stack_offset = 0; - /* Macros to round N up or down to the next A boundary; A must be - a power of two. */ -#define ROUND_DOWN(n,a) ((n) & ~((a)-1)) -#define ROUND_UP(n,a) (((n)+(a)-1) & ~((a)-1)) - /* First ensure that the stack and structure return address (if any) - are properly aligned. The stack has to be at least 64-bit aligned - even on 32-bit machines, because doubles must be 64-bit aligned. - On at least one MIPS variant, stack frames need to be 128-bit - aligned, so we round to this widest known alignment. */ + are properly aligned. The stack has to be at least 64-bit + aligned even on 32-bit machines, because doubles must be 64-bit + aligned. For n32 and n64, stack frames need to be 128-bit + aligned, so we round to this widest known alignment. */ + sp = ROUND_DOWN (sp, 16); struct_addr = ROUND_DOWN (struct_addr, 16); - /* Now make space on the stack for the args. We allocate more + /* Now make space on the stack for the args. We allocate more than necessary for EABI, because the first few arguments are - passed in registers, but that's OK. */ + passed in registers, but that's OK. */ for (argnum = 0; argnum < nargs; argnum++) - len += ROUND_UP (TYPE_LENGTH (VALUE_TYPE (args[argnum])), MIPS_STACK_ARGSIZE); + len += ROUND_UP (TYPE_LENGTH (VALUE_TYPE (args[argnum])), + MIPS_STACK_ARGSIZE); sp -= ROUND_UP (len, 16); if (mips_debug) - fprintf_unfiltered (gdb_stdlog, "mips_push_arguments: sp=0x%lx allocated %d\n", - (long) sp, ROUND_UP (len, 16)); + fprintf_unfiltered (gdb_stdlog, + "mips_eabi_push_arguments: sp=0x%s allocated %d\n", + paddr_nz (sp), ROUND_UP (len, 16)); /* Initialize the integer and float register pointers. */ argreg = A0_REGNUM; float_argreg = FPA0_REGNUM; - /* the struct_return pointer occupies the first parameter-passing reg */ + /* The struct_return pointer occupies the first parameter-passing reg. */ if (struct_return) { if (mips_debug) fprintf_unfiltered (gdb_stdlog, - "mips_push_arguments: struct_return reg=%d 0x%lx\n", - argreg, (long) struct_addr); + "mips_eabi_push_arguments: struct_return reg=%d 0x%s\n", + argreg, paddr_nz (struct_addr)); write_register (argreg++, struct_addr); - if (MIPS_REGS_HAVE_HOME_P) - stack_offset += MIPS_STACK_ARGSIZE; } /* Now load as many as possible of the first arguments into @@ -2228,7 +2677,7 @@ mips_push_arguments (int nargs, for (argnum = 0; argnum < nargs; argnum++) { char *val; - char valbuf[MAX_REGISTER_RAW_SIZE]; + char *valbuf = alloca (MAX_REGISTER_RAW_SIZE); struct value *arg = args[argnum]; struct type *arg_type = check_typedef (VALUE_TYPE (arg)); int len = TYPE_LENGTH (arg_type); @@ -2236,13 +2685,12 @@ mips_push_arguments (int nargs, if (mips_debug) fprintf_unfiltered (gdb_stdlog, - "mips_push_arguments: %d len=%d type=%d", + "mips_eabi_push_arguments: %d len=%d type=%d", argnum + 1, len, (int) typecode); /* The EABI passes structures that do not fit in a register by - reference. In all other cases, pass the structure by value. */ - if (MIPS_EABI - && len > MIPS_SAVED_REGSIZE + reference. */ + if (len > MIPS_SAVED_REGSIZE && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)) { store_address (valbuf, MIPS_SAVED_REGSIZE, VALUE_ADDRESS (arg)); @@ -2258,8 +2706,8 @@ mips_push_arguments (int nargs, /* 32-bit ABIs always start floating point arguments in an even-numbered floating point register. Round the FP register up before the check to see if there are any FP registers - left. Non MIPS_EABI targets also pass the FP in the integer - registers so also round up normal registers. */ + left. Non MIPS_EABI targets also pass the FP in the integer + registers so also round up normal registers. */ if (!FP_REGISTER_DOUBLE && fp_register_arg_p (typecode, arg_type)) { @@ -2278,7 +2726,7 @@ mips_push_arguments (int nargs, because those registers are normally skipped. */ /* MIPS_EABI squeezes a struct that contains a single floating point value into an FP register instead of pushing it onto the - stack. */ + stack. */ if (fp_register_arg_p (typecode, arg_type) && float_argreg <= MIPS_LAST_FP_ARG_REGNUM) { @@ -2293,13 +2741,6 @@ mips_push_arguments (int nargs, fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s", float_argreg, phex (regval, 4)); write_register (float_argreg++, regval); - if (!MIPS_EABI) - { - if (mips_debug) - fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s", - argreg, phex (regval, 4)); - write_register (argreg++, regval); - } /* Write the high word of the double to the odd register(s). */ regval = extract_unsigned_integer (val + 4 - low_offset, 4); @@ -2307,42 +2748,19 @@ mips_push_arguments (int nargs, fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s", float_argreg, phex (regval, 4)); write_register (float_argreg++, regval); - if (!MIPS_EABI) - { - if (mips_debug) - fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s", - argreg, phex (regval, 4)); - write_register (argreg++, regval); - } - } else { /* This is a floating point value that fits entirely in a single register. */ /* On 32 bit ABI's the float_argreg is further adjusted - above to ensure that it is even register aligned. */ + above to ensure that it is even register aligned. */ LONGEST regval = extract_unsigned_integer (val, len); if (mips_debug) fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s", float_argreg, phex (regval, len)); write_register (float_argreg++, regval); - if (!MIPS_EABI) - { - /* CAGNEY: 32 bit MIPS ABI's always reserve two FP - registers for each argument. The below is (my - guess) to ensure that the corresponding integer - register has reserved the same space. */ - if (mips_debug) - fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s", - argreg, phex (regval, len)); - write_register (argreg, regval); - argreg += FP_REGISTER_DOUBLE ? 1 : 2; - } } - /* Reserve space for the FP register. */ - if (MIPS_REGS_HAVE_HOME_P) - stack_offset += ROUND_UP (len, MIPS_STACK_ARGSIZE); } else { @@ -2355,21 +2773,800 @@ mips_push_arguments (int nargs, compatibility, we will put them in both places. */ int odd_sized_struct = ((len > MIPS_SAVED_REGSIZE) && (len % MIPS_SAVED_REGSIZE != 0)); - /* Structures should be aligned to eight bytes (even arg registers) - on MIPS_ABI_O32 if their first member has double precision. */ - if (gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_O32 + + /* Note: Floating-point values that didn't fit into an FP + register are only written to memory. */ + while (len > 0) + { + /* Remember if the argument was written to the stack. */ + int stack_used_p = 0; + int partial_len = + len < MIPS_SAVED_REGSIZE ? len : MIPS_SAVED_REGSIZE; + + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, " -- partial=%d", + partial_len); + + /* Write this portion of the argument to the stack. */ + if (argreg > MIPS_LAST_ARG_REGNUM + || odd_sized_struct + || fp_register_arg_p (typecode, arg_type)) + { + /* Should shorter than int integer values be + promoted to int before being stored? */ + int longword_offset = 0; + CORE_ADDR addr; + stack_used_p = 1; + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + { + if (MIPS_STACK_ARGSIZE == 8 && + (typecode == TYPE_CODE_INT || + typecode == TYPE_CODE_PTR || + typecode == TYPE_CODE_FLT) && len <= 4) + longword_offset = MIPS_STACK_ARGSIZE - len; + else if ((typecode == TYPE_CODE_STRUCT || + typecode == TYPE_CODE_UNION) && + TYPE_LENGTH (arg_type) < MIPS_STACK_ARGSIZE) + longword_offset = MIPS_STACK_ARGSIZE - len; + } + + if (mips_debug) + { + fprintf_unfiltered (gdb_stdlog, " - stack_offset=0x%s", + paddr_nz (stack_offset)); + fprintf_unfiltered (gdb_stdlog, " longword_offset=0x%s", + paddr_nz (longword_offset)); + } + + addr = sp + stack_offset + longword_offset; + + if (mips_debug) + { + int i; + fprintf_unfiltered (gdb_stdlog, " @0x%s ", + paddr_nz (addr)); + for (i = 0; i < partial_len; i++) + { + fprintf_unfiltered (gdb_stdlog, "%02x", + val[i] & 0xff); + } + } + write_memory (addr, val, partial_len); + } + + /* Note!!! This is NOT an else clause. Odd sized + structs may go thru BOTH paths. Floating point + arguments will not. */ + /* Write this portion of the argument to a general + purpose register. */ + if (argreg <= MIPS_LAST_ARG_REGNUM + && !fp_register_arg_p (typecode, arg_type)) + { + LONGEST regval = extract_unsigned_integer (val, partial_len); + + if (mips_debug) + fprintf_filtered (gdb_stdlog, " - reg=%d val=%s", + argreg, + phex (regval, MIPS_SAVED_REGSIZE)); + write_register (argreg, regval); + argreg++; + } + + len -= partial_len; + val += partial_len; + + /* Compute the the offset into the stack at which we + will copy the next parameter. + + In the new EABI (and the NABI32), the stack_offset + only needs to be adjusted when it has been used. */ + + if (stack_used_p) + stack_offset += ROUND_UP (partial_len, MIPS_STACK_ARGSIZE); + } + } + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, "\n"); + } + + /* Return adjusted stack pointer. */ + return sp; +} + +/* N32/N64 version of push_arguments. */ + +static CORE_ADDR +mips_n32n64_push_arguments (int nargs, + struct value **args, + CORE_ADDR sp, + int struct_return, + CORE_ADDR struct_addr) +{ + int argreg; + int float_argreg; + int argnum; + int len = 0; + int stack_offset = 0; + + /* First ensure that the stack and structure return address (if any) + are properly aligned. The stack has to be at least 64-bit + aligned even on 32-bit machines, because doubles must be 64-bit + aligned. For n32 and n64, stack frames need to be 128-bit + aligned, so we round to this widest known alignment. */ + + sp = ROUND_DOWN (sp, 16); + struct_addr = ROUND_DOWN (struct_addr, 16); + + /* Now make space on the stack for the args. */ + for (argnum = 0; argnum < nargs; argnum++) + len += ROUND_UP (TYPE_LENGTH (VALUE_TYPE (args[argnum])), + MIPS_STACK_ARGSIZE); + sp -= ROUND_UP (len, 16); + + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, + "mips_n32n64_push_arguments: sp=0x%s allocated %d\n", + paddr_nz (sp), ROUND_UP (len, 16)); + + /* Initialize the integer and float register pointers. */ + argreg = A0_REGNUM; + float_argreg = FPA0_REGNUM; + + /* The struct_return pointer occupies the first parameter-passing reg. */ + if (struct_return) + { + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, + "mips_n32n64_push_arguments: struct_return reg=%d 0x%s\n", + argreg, paddr_nz (struct_addr)); + write_register (argreg++, struct_addr); + } + + /* Now load as many as possible of the first arguments into + registers, and push the rest onto the stack. Loop thru args + from first to last. */ + for (argnum = 0; argnum < nargs; argnum++) + { + char *val; + char *valbuf = alloca (MAX_REGISTER_RAW_SIZE); + struct value *arg = args[argnum]; + struct type *arg_type = check_typedef (VALUE_TYPE (arg)); + int len = TYPE_LENGTH (arg_type); + enum type_code typecode = TYPE_CODE (arg_type); + + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, + "mips_n32n64_push_arguments: %d len=%d type=%d", + argnum + 1, len, (int) typecode); + + val = (char *) VALUE_CONTENTS (arg); + + if (fp_register_arg_p (typecode, arg_type) + && float_argreg <= MIPS_LAST_FP_ARG_REGNUM) + { + /* This is a floating point value that fits entirely + in a single register. */ + /* On 32 bit ABI's the float_argreg is further adjusted + above to ensure that it is even register aligned. */ + LONGEST regval = extract_unsigned_integer (val, len); + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s", + float_argreg, phex (regval, len)); + write_register (float_argreg++, regval); + + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s", + argreg, phex (regval, len)); + write_register (argreg, regval); + argreg += 1; + } + else + { + /* Copy the argument to general registers or the stack in + register-sized pieces. Large arguments are split between + registers and stack. */ + /* Note: structs whose size is not a multiple of MIPS_REGSIZE + are treated specially: Irix cc passes them in registers + where gcc sometimes puts them on the stack. For maximum + compatibility, we will put them in both places. */ + int odd_sized_struct = ((len > MIPS_SAVED_REGSIZE) && + (len % MIPS_SAVED_REGSIZE != 0)); + /* Note: Floating-point values that didn't fit into an FP + register are only written to memory. */ + while (len > 0) + { + /* Rememer if the argument was written to the stack. */ + int stack_used_p = 0; + int partial_len = len < MIPS_SAVED_REGSIZE ? + len : MIPS_SAVED_REGSIZE; + + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, " -- partial=%d", + partial_len); + + /* Write this portion of the argument to the stack. */ + if (argreg > MIPS_LAST_ARG_REGNUM + || odd_sized_struct + || fp_register_arg_p (typecode, arg_type)) + { + /* Should shorter than int integer values be + promoted to int before being stored? */ + int longword_offset = 0; + CORE_ADDR addr; + stack_used_p = 1; + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + { + if (MIPS_STACK_ARGSIZE == 8 && + (typecode == TYPE_CODE_INT || + typecode == TYPE_CODE_PTR || + typecode == TYPE_CODE_FLT) && len <= 4) + longword_offset = MIPS_STACK_ARGSIZE - len; + } + + if (mips_debug) + { + fprintf_unfiltered (gdb_stdlog, " - stack_offset=0x%s", + paddr_nz (stack_offset)); + fprintf_unfiltered (gdb_stdlog, " longword_offset=0x%s", + paddr_nz (longword_offset)); + } + + addr = sp + stack_offset + longword_offset; + + if (mips_debug) + { + int i; + fprintf_unfiltered (gdb_stdlog, " @0x%s ", + paddr_nz (addr)); + for (i = 0; i < partial_len; i++) + { + fprintf_unfiltered (gdb_stdlog, "%02x", + val[i] & 0xff); + } + } + write_memory (addr, val, partial_len); + } + + /* Note!!! This is NOT an else clause. Odd sized + structs may go thru BOTH paths. Floating point + arguments will not. */ + /* Write this portion of the argument to a general + purpose register. */ + if (argreg <= MIPS_LAST_ARG_REGNUM + && !fp_register_arg_p (typecode, arg_type)) + { + LONGEST regval = extract_unsigned_integer (val, partial_len); + + /* A non-floating-point argument being passed in a + general register. If a struct or union, and if + the remaining length is smaller than the register + size, we have to adjust the register value on + big endian targets. + + It does not seem to be necessary to do the + same for integral types. + + cagney/2001-07-23: gdb/179: Also, GCC, when + outputting LE O32 with sizeof (struct) < + MIPS_SAVED_REGSIZE, generates a left shift as + part of storing the argument in a register a + register (the left shift isn't generated when + sizeof (struct) >= MIPS_SAVED_REGSIZE). Since it + is quite possible that this is GCC contradicting + the LE/O32 ABI, GDB has not been adjusted to + accommodate this. Either someone needs to + demonstrate that the LE/O32 ABI specifies such a + left shift OR this new ABI gets identified as + such and GDB gets tweaked accordingly. */ + + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG + && partial_len < MIPS_SAVED_REGSIZE + && (typecode == TYPE_CODE_STRUCT || + typecode == TYPE_CODE_UNION)) + regval <<= ((MIPS_SAVED_REGSIZE - partial_len) * + TARGET_CHAR_BIT); + + if (mips_debug) + fprintf_filtered (gdb_stdlog, " - reg=%d val=%s", + argreg, + phex (regval, MIPS_SAVED_REGSIZE)); + write_register (argreg, regval); + argreg++; + } + + len -= partial_len; + val += partial_len; + + /* Compute the the offset into the stack at which we + will copy the next parameter. + + In N32 (N64?), the stack_offset only needs to be + adjusted when it has been used. */ + + if (stack_used_p) + stack_offset += ROUND_UP (partial_len, MIPS_STACK_ARGSIZE); + } + } + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, "\n"); + } + + /* Return adjusted stack pointer. */ + return sp; +} + +/* O32 version of push_arguments. */ + +static CORE_ADDR +mips_o32_push_arguments (int nargs, + struct value **args, + CORE_ADDR sp, + int struct_return, + CORE_ADDR struct_addr) +{ + int argreg; + int float_argreg; + int argnum; + int len = 0; + int stack_offset = 0; + + /* First ensure that the stack and structure return address (if any) + are properly aligned. The stack has to be at least 64-bit + aligned even on 32-bit machines, because doubles must be 64-bit + aligned. For n32 and n64, stack frames need to be 128-bit + aligned, so we round to this widest known alignment. */ + + sp = ROUND_DOWN (sp, 16); + struct_addr = ROUND_DOWN (struct_addr, 16); + + /* Now make space on the stack for the args. */ + for (argnum = 0; argnum < nargs; argnum++) + len += ROUND_UP (TYPE_LENGTH (VALUE_TYPE (args[argnum])), + MIPS_STACK_ARGSIZE); + sp -= ROUND_UP (len, 16); + + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, + "mips_o32_push_arguments: sp=0x%s allocated %d\n", + paddr_nz (sp), ROUND_UP (len, 16)); + + /* Initialize the integer and float register pointers. */ + argreg = A0_REGNUM; + float_argreg = FPA0_REGNUM; + + /* The struct_return pointer occupies the first parameter-passing reg. */ + if (struct_return) + { + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, + "mips_o32_push_arguments: struct_return reg=%d 0x%s\n", + argreg, paddr_nz (struct_addr)); + write_register (argreg++, struct_addr); + stack_offset += MIPS_STACK_ARGSIZE; + } + + /* Now load as many as possible of the first arguments into + registers, and push the rest onto the stack. Loop thru args + from first to last. */ + for (argnum = 0; argnum < nargs; argnum++) + { + char *val; + char *valbuf = alloca (MAX_REGISTER_RAW_SIZE); + struct value *arg = args[argnum]; + struct type *arg_type = check_typedef (VALUE_TYPE (arg)); + int len = TYPE_LENGTH (arg_type); + enum type_code typecode = TYPE_CODE (arg_type); + + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, + "mips_o32_push_arguments: %d len=%d type=%d", + argnum + 1, len, (int) typecode); + + val = (char *) VALUE_CONTENTS (arg); + + /* 32-bit ABIs always start floating point arguments in an + even-numbered floating point register. Round the FP register + up before the check to see if there are any FP registers + left. O32/O64 targets also pass the FP in the integer + registers so also round up normal registers. */ + if (!FP_REGISTER_DOUBLE + && fp_register_arg_p (typecode, arg_type)) + { + if ((float_argreg & 1)) + float_argreg++; + } + + /* Floating point arguments passed in registers have to be + treated specially. On 32-bit architectures, doubles + are passed in register pairs; the even register gets + the low word, and the odd register gets the high word. + On O32/O64, the first two floating point arguments are + also copied to general registers, because MIPS16 functions + don't use float registers for arguments. This duplication of + arguments in general registers can't hurt non-MIPS16 functions + because those registers are normally skipped. */ + + if (fp_register_arg_p (typecode, arg_type) + && float_argreg <= MIPS_LAST_FP_ARG_REGNUM) + { + if (!FP_REGISTER_DOUBLE && len == 8) + { + int low_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0; + unsigned long regval; + + /* Write the low word of the double to the even register(s). */ + regval = extract_unsigned_integer (val + low_offset, 4); + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s", + float_argreg, phex (regval, 4)); + write_register (float_argreg++, regval); + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s", + argreg, phex (regval, 4)); + write_register (argreg++, regval); + + /* Write the high word of the double to the odd register(s). */ + regval = extract_unsigned_integer (val + 4 - low_offset, 4); + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s", + float_argreg, phex (regval, 4)); + write_register (float_argreg++, regval); + + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s", + argreg, phex (regval, 4)); + write_register (argreg++, regval); + } + else + { + /* This is a floating point value that fits entirely + in a single register. */ + /* On 32 bit ABI's the float_argreg is further adjusted + above to ensure that it is even register aligned. */ + LONGEST regval = extract_unsigned_integer (val, len); + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s", + float_argreg, phex (regval, len)); + write_register (float_argreg++, regval); + /* CAGNEY: 32 bit MIPS ABI's always reserve two FP + registers for each argument. The below is (my + guess) to ensure that the corresponding integer + register has reserved the same space. */ + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s", + argreg, phex (regval, len)); + write_register (argreg, regval); + argreg += FP_REGISTER_DOUBLE ? 1 : 2; + } + /* Reserve space for the FP register. */ + stack_offset += ROUND_UP (len, MIPS_STACK_ARGSIZE); + } + else + { + /* Copy the argument to general registers or the stack in + register-sized pieces. Large arguments are split between + registers and stack. */ + /* Note: structs whose size is not a multiple of MIPS_REGSIZE + are treated specially: Irix cc passes them in registers + where gcc sometimes puts them on the stack. For maximum + compatibility, we will put them in both places. */ + int odd_sized_struct = ((len > MIPS_SAVED_REGSIZE) && + (len % MIPS_SAVED_REGSIZE != 0)); + /* Structures should be aligned to eight bytes (even arg registers) + on MIPS_ABI_O32, if their first member has double precision. */ + if (MIPS_SAVED_REGSIZE < 8 + && mips_type_needs_double_align (arg_type)) + { + if ((argreg & 1)) + argreg++; + } + /* Note: Floating-point values that didn't fit into an FP + register are only written to memory. */ + while (len > 0) + { + /* Remember if the argument was written to the stack. */ + int stack_used_p = 0; + int partial_len = + len < MIPS_SAVED_REGSIZE ? len : MIPS_SAVED_REGSIZE; + + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, " -- partial=%d", + partial_len); + + /* Write this portion of the argument to the stack. */ + if (argreg > MIPS_LAST_ARG_REGNUM + || odd_sized_struct + || fp_register_arg_p (typecode, arg_type)) + { + /* Should shorter than int integer values be + promoted to int before being stored? */ + int longword_offset = 0; + CORE_ADDR addr; + stack_used_p = 1; + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + { + if (MIPS_STACK_ARGSIZE == 8 && + (typecode == TYPE_CODE_INT || + typecode == TYPE_CODE_PTR || + typecode == TYPE_CODE_FLT) && len <= 4) + longword_offset = MIPS_STACK_ARGSIZE - len; + } + + if (mips_debug) + { + fprintf_unfiltered (gdb_stdlog, " - stack_offset=0x%s", + paddr_nz (stack_offset)); + fprintf_unfiltered (gdb_stdlog, " longword_offset=0x%s", + paddr_nz (longword_offset)); + } + + addr = sp + stack_offset + longword_offset; + + if (mips_debug) + { + int i; + fprintf_unfiltered (gdb_stdlog, " @0x%s ", + paddr_nz (addr)); + for (i = 0; i < partial_len; i++) + { + fprintf_unfiltered (gdb_stdlog, "%02x", + val[i] & 0xff); + } + } + write_memory (addr, val, partial_len); + } + + /* Note!!! This is NOT an else clause. Odd sized + structs may go thru BOTH paths. Floating point + arguments will not. */ + /* Write this portion of the argument to a general + purpose register. */ + if (argreg <= MIPS_LAST_ARG_REGNUM + && !fp_register_arg_p (typecode, arg_type)) + { + LONGEST regval = extract_signed_integer (val, partial_len); + /* Value may need to be sign extended, because + MIPS_REGSIZE != MIPS_SAVED_REGSIZE. */ + + /* A non-floating-point argument being passed in a + general register. If a struct or union, and if + the remaining length is smaller than the register + size, we have to adjust the register value on + big endian targets. + + It does not seem to be necessary to do the + same for integral types. + + Also don't do this adjustment on O64 binaries. + + cagney/2001-07-23: gdb/179: Also, GCC, when + outputting LE O32 with sizeof (struct) < + MIPS_SAVED_REGSIZE, generates a left shift as + part of storing the argument in a register a + register (the left shift isn't generated when + sizeof (struct) >= MIPS_SAVED_REGSIZE). Since it + is quite possible that this is GCC contradicting + the LE/O32 ABI, GDB has not been adjusted to + accommodate this. Either someone needs to + demonstrate that the LE/O32 ABI specifies such a + left shift OR this new ABI gets identified as + such and GDB gets tweaked accordingly. */ + + if (MIPS_SAVED_REGSIZE < 8 + && TARGET_BYTE_ORDER == BFD_ENDIAN_BIG + && partial_len < MIPS_SAVED_REGSIZE + && (typecode == TYPE_CODE_STRUCT || + typecode == TYPE_CODE_UNION)) + regval <<= ((MIPS_SAVED_REGSIZE - partial_len) * + TARGET_CHAR_BIT); + + if (mips_debug) + fprintf_filtered (gdb_stdlog, " - reg=%d val=%s", + argreg, + phex (regval, MIPS_SAVED_REGSIZE)); + write_register (argreg, regval); + argreg++; + + /* Prevent subsequent floating point arguments from + being passed in floating point registers. */ + float_argreg = MIPS_LAST_FP_ARG_REGNUM + 1; + } + + len -= partial_len; + val += partial_len; + + /* Compute the the offset into the stack at which we + will copy the next parameter. + + In older ABIs, the caller reserved space for + registers that contained arguments. This was loosely + refered to as their "home". Consequently, space is + always allocated. */ + + stack_offset += ROUND_UP (partial_len, MIPS_STACK_ARGSIZE); + } + } + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, "\n"); + } + + /* Return adjusted stack pointer. */ + return sp; +} + +/* O64 version of push_arguments. */ + +static CORE_ADDR +mips_o64_push_arguments (int nargs, + struct value **args, + CORE_ADDR sp, + int struct_return, + CORE_ADDR struct_addr) +{ + int argreg; + int float_argreg; + int argnum; + int len = 0; + int stack_offset = 0; + + /* First ensure that the stack and structure return address (if any) + are properly aligned. The stack has to be at least 64-bit + aligned even on 32-bit machines, because doubles must be 64-bit + aligned. For n32 and n64, stack frames need to be 128-bit + aligned, so we round to this widest known alignment. */ + + sp = ROUND_DOWN (sp, 16); + struct_addr = ROUND_DOWN (struct_addr, 16); + + /* Now make space on the stack for the args. */ + for (argnum = 0; argnum < nargs; argnum++) + len += ROUND_UP (TYPE_LENGTH (VALUE_TYPE (args[argnum])), + MIPS_STACK_ARGSIZE); + sp -= ROUND_UP (len, 16); + + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, + "mips_o64_push_arguments: sp=0x%s allocated %d\n", + paddr_nz (sp), ROUND_UP (len, 16)); + + /* Initialize the integer and float register pointers. */ + argreg = A0_REGNUM; + float_argreg = FPA0_REGNUM; + + /* The struct_return pointer occupies the first parameter-passing reg. */ + if (struct_return) + { + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, + "mips_o64_push_arguments: struct_return reg=%d 0x%s\n", + argreg, paddr_nz (struct_addr)); + write_register (argreg++, struct_addr); + stack_offset += MIPS_STACK_ARGSIZE; + } + + /* Now load as many as possible of the first arguments into + registers, and push the rest onto the stack. Loop thru args + from first to last. */ + for (argnum = 0; argnum < nargs; argnum++) + { + char *val; + char *valbuf = alloca (MAX_REGISTER_RAW_SIZE); + struct value *arg = args[argnum]; + struct type *arg_type = check_typedef (VALUE_TYPE (arg)); + int len = TYPE_LENGTH (arg_type); + enum type_code typecode = TYPE_CODE (arg_type); + + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, + "mips_o64_push_arguments: %d len=%d type=%d", + argnum + 1, len, (int) typecode); + + val = (char *) VALUE_CONTENTS (arg); + + /* 32-bit ABIs always start floating point arguments in an + even-numbered floating point register. Round the FP register + up before the check to see if there are any FP registers + left. O32/O64 targets also pass the FP in the integer + registers so also round up normal registers. */ + if (!FP_REGISTER_DOUBLE + && fp_register_arg_p (typecode, arg_type)) + { + if ((float_argreg & 1)) + float_argreg++; + } + + /* Floating point arguments passed in registers have to be + treated specially. On 32-bit architectures, doubles + are passed in register pairs; the even register gets + the low word, and the odd register gets the high word. + On O32/O64, the first two floating point arguments are + also copied to general registers, because MIPS16 functions + don't use float registers for arguments. This duplication of + arguments in general registers can't hurt non-MIPS16 functions + because those registers are normally skipped. */ + + if (fp_register_arg_p (typecode, arg_type) + && float_argreg <= MIPS_LAST_FP_ARG_REGNUM) + { + if (!FP_REGISTER_DOUBLE && len == 8) + { + int low_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0; + unsigned long regval; + + /* Write the low word of the double to the even register(s). */ + regval = extract_unsigned_integer (val + low_offset, 4); + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s", + float_argreg, phex (regval, 4)); + write_register (float_argreg++, regval); + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s", + argreg, phex (regval, 4)); + write_register (argreg++, regval); + + /* Write the high word of the double to the odd register(s). */ + regval = extract_unsigned_integer (val + 4 - low_offset, 4); + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s", + float_argreg, phex (regval, 4)); + write_register (float_argreg++, regval); + + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s", + argreg, phex (regval, 4)); + write_register (argreg++, regval); + } + else + { + /* This is a floating point value that fits entirely + in a single register. */ + /* On 32 bit ABI's the float_argreg is further adjusted + above to ensure that it is even register aligned. */ + LONGEST regval = extract_unsigned_integer (val, len); + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s", + float_argreg, phex (regval, len)); + write_register (float_argreg++, regval); + /* CAGNEY: 32 bit MIPS ABI's always reserve two FP + registers for each argument. The below is (my + guess) to ensure that the corresponding integer + register has reserved the same space. */ + if (mips_debug) + fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s", + argreg, phex (regval, len)); + write_register (argreg, regval); + argreg += FP_REGISTER_DOUBLE ? 1 : 2; + } + /* Reserve space for the FP register. */ + stack_offset += ROUND_UP (len, MIPS_STACK_ARGSIZE); + } + else + { + /* Copy the argument to general registers or the stack in + register-sized pieces. Large arguments are split between + registers and stack. */ + /* Note: structs whose size is not a multiple of MIPS_REGSIZE + are treated specially: Irix cc passes them in registers + where gcc sometimes puts them on the stack. For maximum + compatibility, we will put them in both places. */ + int odd_sized_struct = ((len > MIPS_SAVED_REGSIZE) && + (len % MIPS_SAVED_REGSIZE != 0)); + /* Structures should be aligned to eight bytes (even arg registers) + on MIPS_ABI_O32, if their first member has double precision. */ + if (MIPS_SAVED_REGSIZE < 8 && mips_type_needs_double_align (arg_type)) { if ((argreg & 1)) argreg++; } /* Note: Floating-point values that didn't fit into an FP - register are only written to memory. */ + register are only written to memory. */ while (len > 0) { - /* Rememer if the argument was written to the stack. */ + /* Remember if the argument was written to the stack. */ int stack_used_p = 0; - int partial_len = len < MIPS_SAVED_REGSIZE ? len : MIPS_SAVED_REGSIZE; + int partial_len = + len < MIPS_SAVED_REGSIZE ? len : MIPS_SAVED_REGSIZE; if (mips_debug) fprintf_unfiltered (gdb_stdlog, " -- partial=%d", @@ -2392,29 +3589,27 @@ mips_push_arguments (int nargs, typecode == TYPE_CODE_PTR || typecode == TYPE_CODE_FLT) && len <= 4) longword_offset = MIPS_STACK_ARGSIZE - len; - else if ((typecode == TYPE_CODE_STRUCT || - typecode == TYPE_CODE_UNION) && - TYPE_LENGTH (arg_type) < MIPS_STACK_ARGSIZE) - longword_offset = MIPS_STACK_ARGSIZE - len; } if (mips_debug) { - fprintf_unfiltered (gdb_stdlog, " - stack_offset=0x%lx", - (long) stack_offset); - fprintf_unfiltered (gdb_stdlog, " longword_offset=0x%lx", - (long) longword_offset); + fprintf_unfiltered (gdb_stdlog, " - stack_offset=0x%s", + paddr_nz (stack_offset)); + fprintf_unfiltered (gdb_stdlog, " longword_offset=0x%s", + paddr_nz (longword_offset)); } - + addr = sp + stack_offset + longword_offset; if (mips_debug) { int i; - fprintf_unfiltered (gdb_stdlog, " @0x%lx ", (long) addr); + fprintf_unfiltered (gdb_stdlog, " @0x%s ", + paddr_nz (addr)); for (i = 0; i < partial_len; i++) { - fprintf_unfiltered (gdb_stdlog, "%02x", val[i] & 0xff); + fprintf_unfiltered (gdb_stdlog, "%02x", + val[i] & 0xff); } } write_memory (addr, val, partial_len); @@ -2422,15 +3617,17 @@ mips_push_arguments (int nargs, /* Note!!! This is NOT an else clause. Odd sized structs may go thru BOTH paths. Floating point - arguments will not. */ + arguments will not. */ /* Write this portion of the argument to a general - purpose register. */ + purpose register. */ if (argreg <= MIPS_LAST_ARG_REGNUM && !fp_register_arg_p (typecode, arg_type)) { - LONGEST regval = extract_unsigned_integer (val, partial_len); + LONGEST regval = extract_signed_integer (val, partial_len); + /* Value may need to be sign extended, because + MIPS_REGSIZE != MIPS_SAVED_REGSIZE. */ - /* A non-floating-point argument being passed in a + /* A non-floating-point argument being passed in a general register. If a struct or union, and if the remaining length is smaller than the register size, we have to adjust the register value on @@ -2439,8 +3636,7 @@ mips_push_arguments (int nargs, It does not seem to be necessary to do the same for integral types. - Also don't do this adjustment on EABI and O64 - binaries. + Also don't do this adjustment on O64 binaries. cagney/2001-07-23: gdb/179: Also, GCC, when outputting LE O32 with sizeof (struct) < @@ -2455,8 +3651,7 @@ mips_push_arguments (int nargs, left shift OR this new ABI gets identified as such and GDB gets tweaked accordingly. */ - if (!MIPS_EABI - && MIPS_SAVED_REGSIZE < 8 + if (MIPS_SAVED_REGSIZE < 8 && TARGET_BYTE_ORDER == BFD_ENDIAN_BIG && partial_len < MIPS_SAVED_REGSIZE && (typecode == TYPE_CODE_STRUCT || @@ -2471,11 +3666,9 @@ mips_push_arguments (int nargs, write_register (argreg, regval); argreg++; - /* If this is the old ABI, prevent subsequent floating - point arguments from being passed in floating point - registers. */ - if (!MIPS_EABI) - float_argreg = MIPS_LAST_FP_ARG_REGNUM + 1; + /* Prevent subsequent floating point arguments from + being passed in floating point registers. */ + float_argreg = MIPS_LAST_FP_ARG_REGNUM + 1; } len -= partial_len; @@ -2487,13 +3680,9 @@ mips_push_arguments (int nargs, In older ABIs, the caller reserved space for registers that contained arguments. This was loosely refered to as their "home". Consequently, space is - always allocated. + always allocated. */ - In the new EABI (and the NABI32), the stack_offset - only needs to be adjusted when it has been used.. */ - - if (MIPS_REGS_HAVE_HOME_P || stack_used_p) - stack_offset += ROUND_UP (partial_len, MIPS_STACK_ARGSIZE); + stack_offset += ROUND_UP (partial_len, MIPS_STACK_ARGSIZE); } } if (mips_debug) @@ -2504,7 +3693,7 @@ mips_push_arguments (int nargs, return sp; } -CORE_ADDR +static CORE_ADDR mips_push_return_address (CORE_ADDR pc, CORE_ADDR sp) { /* Set the return address register to point to the entry @@ -2516,7 +3705,7 @@ mips_push_return_address (CORE_ADDR pc, CORE_ADDR sp) static void mips_push_register (CORE_ADDR * sp, int regno) { - char buffer[MAX_REGISTER_RAW_SIZE]; + char *buffer = alloca (MAX_REGISTER_RAW_SIZE); int regsize; int offset; if (MIPS_SAVED_REGSIZE < REGISTER_RAW_SIZE (regno)) @@ -2532,14 +3721,14 @@ mips_push_register (CORE_ADDR * sp, int regno) offset = 0; } *sp -= regsize; - read_register_gen (regno, buffer); + deprecated_read_register_gen (regno, buffer); write_memory (*sp, buffer + offset, regsize); } /* MASK(i,j) == (1<extra_info->proc_desc; + if (DEPRECATED_PC_IN_CALL_DUMMY (frame->pc, 0, 0)) + { + generic_pop_dummy_frame (); + flush_cached_frames (); + return; + } + write_register (PC_REGNUM, FRAME_SAVED_PC (frame)); if (frame->saved_regs == NULL) - mips_find_saved_regs (frame); + FRAME_INIT_SAVED_REGS (frame); for (regnum = 0; regnum < NUM_REGS; regnum++) - { - if (regnum != SP_REGNUM && regnum != PC_REGNUM - && frame->saved_regs[regnum]) - write_register (regnum, - read_memory_integer (frame->saved_regs[regnum], - MIPS_SAVED_REGSIZE)); - } + if (regnum != SP_REGNUM && regnum != PC_REGNUM + && frame->saved_regs[regnum]) + { + /* Floating point registers must not be sign extended, + in case MIPS_SAVED_REGSIZE = 4 but sizeof (FP0_REGNUM) == 8. */ + + if (FP0_REGNUM <= regnum && regnum < FP0_REGNUM + 32) + write_register (regnum, + read_memory_unsigned_integer (frame->saved_regs[regnum], + MIPS_SAVED_REGSIZE)); + else + write_register (regnum, + read_memory_integer (frame->saved_regs[regnum], + MIPS_SAVED_REGSIZE)); + } + write_register (SP_REGNUM, new_sp); flush_cached_frames (); @@ -2676,34 +3880,158 @@ mips_pop_frame (void) } } +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); +} + +/* Floating point register management. + + Background: MIPS1 & 2 fp registers are 32 bits wide. To support + 64bit operations, these early MIPS cpus treat fp register pairs + (f0,f1) as a single register (d0). Later MIPS cpu's have 64 bit fp + registers and offer a compatibility mode that emulates the MIPS2 fp + model. When operating in MIPS2 fp compat mode, later cpu's split + double precision floats into two 32-bit chunks and store them in + consecutive fp regs. To display 64-bit floats stored in this + fashion, we have to combine 32 bits from f0 and 32 bits from f1. + Throw in user-configurable endianness and you have a real mess. + + The way this works is: + - If we are in 32-bit mode or on a 32-bit processor, then a 64-bit + double-precision value will be split across two logical registers. + The lower-numbered logical register will hold the low-order bits, + regardless of the processor's endianness. + - If we are on a 64-bit processor, and we are looking for a + single-precision value, it will be in the low ordered bits + of a 64-bit GPR (after mfc1, for example) or a 64-bit register + save slot in memory. + - If we are in 64-bit mode, everything is straightforward. + + Note that this code only deals with "live" registers at the top of the + stack. We will attempt to deal with saved registers later, when + the raw/cooked register interface is in place. (We need a general + interface that can deal with dynamic saved register sizes -- fp + regs could be 32 bits wide in one frame and 64 on the frame above + and below). */ + +static struct type * +mips_float_register_type (void) +{ + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + return builtin_type_ieee_single_big; + else + return builtin_type_ieee_single_little; +} + +static struct type * +mips_double_register_type (void) +{ + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + return builtin_type_ieee_double_big; + else + return builtin_type_ieee_double_little; +} + +/* Copy a 32-bit single-precision value from the current frame + into rare_buffer. */ + +static void +mips_read_fp_register_single (int regno, char *rare_buffer) +{ + int raw_size = REGISTER_RAW_SIZE (regno); + char *raw_buffer = alloca (raw_size); + + if (!frame_register_read (deprecated_selected_frame, regno, raw_buffer)) + error ("can't read register %d (%s)", regno, REGISTER_NAME (regno)); + if (raw_size == 8) + { + /* We have a 64-bit value for this register. Find the low-order + 32 bits. */ + int offset; + + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + offset = 4; + else + offset = 0; + + memcpy (rare_buffer, raw_buffer + offset, 4); + } + else + { + memcpy (rare_buffer, raw_buffer, 4); + } +} + +/* Copy a 64-bit double-precision value from the current frame into + rare_buffer. This may include getting half of it from the next + register. */ + +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); + } + } +} + static void mips_print_register (int regnum, int all) { - char raw_buffer[MAX_REGISTER_RAW_SIZE]; + char *raw_buffer = alloca (MAX_REGISTER_RAW_SIZE); /* Get the data in raw format. */ - if (read_relative_register_raw_bytes (regnum, raw_buffer)) + if (!frame_register_read (deprecated_selected_frame, regnum, raw_buffer)) { printf_filtered ("%s: [Invalid]", REGISTER_NAME (regnum)); return; } - /* If an even floating point register, also print as double. */ + /* If we have a actual 32-bit floating point register (or we are in + 32-bit compatibility mode), and the register is even-numbered, + also print it as a double (spanning two registers). */ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT + && (REGISTER_RAW_SIZE (regnum) == 4 + || mips2_fp_compat ()) && !((regnum - FP0_REGNUM) & 1)) - if (REGISTER_RAW_SIZE (regnum) == 4) /* this would be silly on MIPS64 or N32 (Irix 6) */ - { - char dbuffer[2 * MAX_REGISTER_RAW_SIZE]; + { + char *dbuffer = alloca (2 * MAX_REGISTER_RAW_SIZE); - read_relative_register_raw_bytes (regnum, dbuffer); - read_relative_register_raw_bytes (regnum + 1, dbuffer + MIPS_REGSIZE); - REGISTER_CONVERT_TO_TYPE (regnum, builtin_type_double, dbuffer); + mips_read_fp_register_double (regnum, dbuffer); - printf_filtered ("(d%d: ", regnum - FP0_REGNUM); - val_print (builtin_type_double, dbuffer, 0, 0, - gdb_stdout, 0, 1, 0, Val_pretty_default); - printf_filtered ("); "); - } + printf_filtered ("(d%d: ", regnum - FP0_REGNUM); + val_print (mips_double_register_type (), dbuffer, 0, 0, + gdb_stdout, 0, 1, 0, Val_pretty_default); + printf_filtered ("); "); + } fputs_filtered (REGISTER_NAME (regnum), gdb_stdout); /* The problem with printing numeric register names (r26, etc.) is that @@ -2717,15 +4045,17 @@ mips_print_register (int regnum, int all) /* If virtual format is floating, print it that way. */ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT) - if (FP_REGISTER_DOUBLE) - { /* show 8-byte floats as float AND double: */ + if (REGISTER_RAW_SIZE (regnum) == 8 && !mips2_fp_compat ()) + { + /* We have a meaningful 64-bit value in this register. Show + it as a 32-bit float and a 64-bit double. */ int offset = 4 * (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG); printf_filtered (" (float) "); - val_print (builtin_type_float, raw_buffer + offset, 0, 0, + val_print (mips_float_register_type (), raw_buffer + offset, 0, 0, gdb_stdout, 0, 1, 0, Val_pretty_default); printf_filtered (", (double) "); - val_print (builtin_type_double, raw_buffer, 0, 0, + val_print (mips_double_register_type (), raw_buffer, 0, 0, gdb_stdout, 0, 1, 0, Val_pretty_default); } else @@ -2740,47 +4070,37 @@ mips_print_register (int regnum, int all) offset = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum); else offset = 0; - + print_scalar_formatted (raw_buffer + offset, REGISTER_VIRTUAL_TYPE (regnum), 'x', 0, gdb_stdout); } } -/* Replacement for generic do_registers_info. +/* Replacement for generic do_registers_info. Print regs in pretty columns. */ static int do_fp_register_row (int regnum) { /* do values for FP (float) regs */ - char *raw_buffer[2]; - char *dbl_buffer; - /* use HI and LO to control the order of combining two flt regs */ - int HI = (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG); - int LO = (TARGET_BYTE_ORDER != BFD_ENDIAN_BIG); + char *raw_buffer; double doub, flt1, flt2; /* doubles extracted from raw hex data */ int inv1, inv2, inv3; - raw_buffer[0] = (char *) alloca (REGISTER_RAW_SIZE (FP0_REGNUM)); - raw_buffer[1] = (char *) alloca (REGISTER_RAW_SIZE (FP0_REGNUM)); - dbl_buffer = (char *) alloca (2 * REGISTER_RAW_SIZE (FP0_REGNUM)); + raw_buffer = (char *) alloca (2 * REGISTER_RAW_SIZE (FP0_REGNUM)); - /* Get the data in raw format. */ - if (read_relative_register_raw_bytes (regnum, raw_buffer[HI])) - error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum)); - if (REGISTER_RAW_SIZE (regnum) == 4) + if (REGISTER_RAW_SIZE (regnum) == 4 || mips2_fp_compat ()) { - /* 4-byte registers: we can fit two registers per row. */ - /* Also print every pair of 4-byte regs as an 8-byte double. */ - if (read_relative_register_raw_bytes (regnum + 1, raw_buffer[LO])) - error ("can't read register %d (%s)", - regnum + 1, REGISTER_NAME (regnum + 1)); - - /* copy the two floats into one double, and unpack both */ - memcpy (dbl_buffer, raw_buffer, 2 * REGISTER_RAW_SIZE (FP0_REGNUM)); - flt1 = unpack_double (builtin_type_float, raw_buffer[HI], &inv1); - flt2 = unpack_double (builtin_type_float, raw_buffer[LO], &inv2); - doub = unpack_double (builtin_type_double, dbl_buffer, &inv3); + /* 4-byte registers: we can fit two registers per row. */ + /* Also print every pair of 4-byte regs as an 8-byte double. */ + mips_read_fp_register_single (regnum, raw_buffer); + flt1 = unpack_double (mips_float_register_type (), raw_buffer, &inv1); + + mips_read_fp_register_single (regnum + 1, raw_buffer); + flt2 = unpack_double (mips_float_register_type (), raw_buffer, &inv2); + + mips_read_fp_register_double (regnum, raw_buffer); + doub = unpack_double (mips_double_register_type (), raw_buffer, &inv3); printf_filtered (" %-5s", REGISTER_NAME (regnum)); if (inv1) @@ -2805,13 +4125,13 @@ do_fp_register_row (int regnum) regnum += 2; } else - { /* eight byte registers: print each one as float AND as double. */ - int offset = 4 * (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG); + { + /* Eight byte registers: print each one as float AND as double. */ + mips_read_fp_register_single (regnum, raw_buffer); + flt1 = unpack_double (mips_double_register_type (), raw_buffer, &inv1); - memcpy (dbl_buffer, raw_buffer[HI], 2 * REGISTER_RAW_SIZE (FP0_REGNUM)); - flt1 = unpack_double (builtin_type_float, - &raw_buffer[HI][offset], &inv1); - doub = unpack_double (builtin_type_double, dbl_buffer, &inv3); + mips_read_fp_register_double (regnum, raw_buffer); + doub = unpack_double (mips_double_register_type (), raw_buffer, &inv3); printf_filtered (" %-5s: ", REGISTER_NAME (regnum)); if (inv1) @@ -2838,7 +4158,7 @@ static int do_gp_register_row (int regnum) { /* do values for GP (int) regs */ - char raw_buffer[MAX_REGISTER_RAW_SIZE]; + char *raw_buffer = alloca (MAX_REGISTER_RAW_SIZE); int ncols = (MIPS_REGSIZE == 8 ? 4 : 8); /* display cols per row */ int col, byte; int start_regnum = regnum; @@ -2869,7 +4189,7 @@ do_gp_register_row (int regnum) if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT) break; /* end row: reached FP register */ /* OK: get the data in raw format. */ - if (read_relative_register_raw_bytes (regnum, raw_buffer)) + if (!frame_register_read (deprecated_selected_frame, regnum, raw_buffer)) error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum)); /* pad small registers */ for (byte = 0; byte < (MIPS_REGSIZE - REGISTER_VIRTUAL_SIZE (regnum)); byte++) @@ -2896,7 +4216,7 @@ do_gp_register_row (int regnum) /* MIPS_DO_REGISTERS_INFO(): called by "info register" command */ -void +static void mips_do_registers_info (int regnum, int fpregs) { if (regnum != -1) /* do one specified register */ @@ -2921,16 +4241,7 @@ mips_do_registers_info (int regnum, int fpregs) else regnum = do_gp_register_row (regnum); /* GP (int) regs */ } - } -} - -/* Return number of args passed to a frame. described by FIP. - Can return -1, meaning no way to tell. */ - -int -mips_frame_num_args (struct frame_info *frame) -{ - return -1; + } } /* Is this a branch with a delay slot? */ @@ -3171,7 +4482,7 @@ mips16_skip_prologue (CORE_ADDR pc) We must skip more in the case where part of the prologue is in the delay slot of a non-prologue instruction). */ -CORE_ADDR +static CORE_ADDR mips_skip_prologue (CORE_ADDR pc) { /* See if we can determine the end of the prologue via the symbol table. @@ -3306,10 +4617,29 @@ return_value_location (struct type *valtype, /* Given a return value in `regbuf' with a type `valtype', extract and copy its value into `valbuf'. */ -void -mips_extract_return_value (struct type *valtype, - char regbuf[REGISTER_BYTES], - char *valbuf) +static void +mips_eabi_extract_return_value (struct type *valtype, + char regbuf[REGISTER_BYTES], + char *valbuf) +{ + struct return_value_word lo; + struct return_value_word hi; + return_value_location (valtype, &hi, &lo); + + memcpy (valbuf + lo.buf_offset, + regbuf + REGISTER_BYTE (lo.reg) + lo.reg_offset, + lo.len); + + if (hi.len > 0) + memcpy (valbuf + hi.buf_offset, + regbuf + REGISTER_BYTE (hi.reg) + hi.reg_offset, + hi.len); +} + +static void +mips_o64_extract_return_value (struct type *valtype, + char regbuf[REGISTER_BYTES], + char *valbuf) { struct return_value_word lo; struct return_value_word hi; @@ -3328,34 +4658,321 @@ mips_extract_return_value (struct type *valtype, /* Given a return value in `valbuf' with a type `valtype', write it's value into the appropriate register. */ -void -mips_store_return_value (struct type *valtype, char *valbuf) +static void +mips_eabi_store_return_value (struct type *valtype, char *valbuf) +{ + char *raw_buffer = alloca (MAX_REGISTER_RAW_SIZE); + struct return_value_word lo; + struct return_value_word hi; + return_value_location (valtype, &hi, &lo); + + memset (raw_buffer, 0, sizeof (raw_buffer)); + memcpy (raw_buffer + lo.reg_offset, valbuf + lo.buf_offset, lo.len); + deprecated_write_register_bytes (REGISTER_BYTE (lo.reg), raw_buffer, + REGISTER_RAW_SIZE (lo.reg)); + + if (hi.len > 0) + { + memset (raw_buffer, 0, sizeof (raw_buffer)); + memcpy (raw_buffer + hi.reg_offset, valbuf + hi.buf_offset, hi.len); + deprecated_write_register_bytes (REGISTER_BYTE (hi.reg), raw_buffer, + REGISTER_RAW_SIZE (hi.reg)); + } +} + +static void +mips_o64_store_return_value (struct type *valtype, char *valbuf) { - char raw_buffer[MAX_REGISTER_RAW_SIZE]; + char *raw_buffer = alloca (MAX_REGISTER_RAW_SIZE); struct return_value_word lo; struct return_value_word hi; return_value_location (valtype, &hi, &lo); memset (raw_buffer, 0, sizeof (raw_buffer)); memcpy (raw_buffer + lo.reg_offset, valbuf + lo.buf_offset, lo.len); - write_register_bytes (REGISTER_BYTE (lo.reg), - raw_buffer, - REGISTER_RAW_SIZE (lo.reg)); + deprecated_write_register_bytes (REGISTER_BYTE (lo.reg), raw_buffer, + REGISTER_RAW_SIZE (lo.reg)); if (hi.len > 0) { memset (raw_buffer, 0, sizeof (raw_buffer)); memcpy (raw_buffer + hi.reg_offset, valbuf + hi.buf_offset, hi.len); - write_register_bytes (REGISTER_BYTE (hi.reg), - raw_buffer, - REGISTER_RAW_SIZE (hi.reg)); + deprecated_write_register_bytes (REGISTER_BYTE (hi.reg), raw_buffer, + REGISTER_RAW_SIZE (hi.reg)); + } +} + +/* O32 ABI stuff. */ + +static void +mips_o32_xfer_return_value (struct type *type, + struct regcache *regcache, + bfd_byte *in, const bfd_byte *out) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + if (TYPE_CODE (type) == TYPE_CODE_FLT + && TYPE_LENGTH (type) == 4 + && tdep->mips_fpu_type != MIPS_FPU_NONE) + { + /* A single-precision floating-point value. It fits in the + 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), + 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 (???). */ + if (mips_debug) + fprintf_unfiltered (gdb_stderr, "Return float in $fp0/$fp1\n"); + switch (TARGET_BYTE_ORDER) + { + case BFD_ENDIAN_LITTLE: + mips_xfer_register (regcache, FP0_REGNUM + 0, 4, + TARGET_BYTE_ORDER, in, out, 0); + mips_xfer_register (regcache, FP0_REGNUM + 1, 4, + TARGET_BYTE_ORDER, in, out, 4); + break; + case BFD_ENDIAN_BIG: + mips_xfer_register (regcache, FP0_REGNUM + 1, 4, + TARGET_BYTE_ORDER, in, out, 0); + mips_xfer_register (regcache, FP0_REGNUM + 0, 4, + TARGET_BYTE_ORDER, in, out, 4); + break; + default: + internal_error (__FILE__, __LINE__, "bad switch"); + } + } +#if 0 + else if (TYPE_CODE (type) == TYPE_CODE_STRUCT + && TYPE_NFIELDS (type) <= 2 + && TYPE_NFIELDS (type) >= 1 + && ((TYPE_NFIELDS (type) == 1 + && (TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) + == TYPE_CODE_FLT)) + || (TYPE_NFIELDS (type) == 2 + && (TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) + == TYPE_CODE_FLT) + && (TYPE_CODE (TYPE_FIELD_TYPE (type, 1)) + == TYPE_CODE_FLT))) + && tdep->mips_fpu_type != MIPS_FPU_NONE) + { + /* A struct that contains one or two floats. Each value is part + in the least significant part of their floating point + register.. */ + bfd_byte *reg = alloca (MAX_REGISTER_RAW_SIZE); + int regnum; + int field; + for (field = 0, regnum = FP0_REGNUM; + field < TYPE_NFIELDS (type); + field++, regnum += 2) + { + int offset = (FIELD_BITPOS (TYPE_FIELDS (type)[field]) + / 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)), + TARGET_BYTE_ORDER, in, out, offset); + } + } +#endif +#if 0 + else if (TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION) + { + /* A structure or union. Extract the left justified value, + regardless of the byte order. I.e. DO NOT USE + mips_xfer_lower. */ + int offset; + int regnum; + for (offset = 0, regnum = V0_REGNUM; + offset < TYPE_LENGTH (type); + offset += REGISTER_RAW_SIZE (regnum), regnum++) + { + int xfer = REGISTER_RAW_SIZE (regnum); + if (offset + xfer > TYPE_LENGTH (type)) + xfer = TYPE_LENGTH (type) - offset; + 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); + } + } +#endif + else + { + /* A scalar extract each part but least-significant-byte + justified. o32 thinks registers are 4 byte, regardless of + the ISA. mips_stack_argsize controls this. */ + int offset; + int regnum; + for (offset = 0, regnum = V0_REGNUM; + offset < TYPE_LENGTH (type); + offset += mips_stack_argsize (), regnum++) + { + int xfer = mips_stack_argsize (); + int pos = 0; + if (offset + xfer > TYPE_LENGTH (type)) + xfer = TYPE_LENGTH (type) - offset; + 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); + } + } +} + +static void +mips_o32_extract_return_value (struct type *type, + struct regcache *regcache, + void *valbuf) +{ + mips_o32_xfer_return_value (type, regcache, valbuf, NULL); +} + +static void +mips_o32_store_return_value (struct type *type, char *valbuf) +{ + mips_o32_xfer_return_value (type, current_regcache, NULL, valbuf); +} + +/* N32/N44 ABI stuff. */ + +static void +mips_n32n64_xfer_return_value (struct type *type, + struct regcache *regcache, + bfd_byte *in, const bfd_byte *out) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + if (TYPE_CODE (type) == TYPE_CODE_FLT + && tdep->mips_fpu_type != MIPS_FPU_NONE) + { + /* A floating-point value belongs in the 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), + TARGET_BYTE_ORDER, in, out, 0); + } + else if (TYPE_CODE (type) == TYPE_CODE_STRUCT + && TYPE_NFIELDS (type) <= 2 + && TYPE_NFIELDS (type) >= 1 + && ((TYPE_NFIELDS (type) == 1 + && (TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) + == TYPE_CODE_FLT)) + || (TYPE_NFIELDS (type) == 2 + && (TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) + == TYPE_CODE_FLT) + && (TYPE_CODE (TYPE_FIELD_TYPE (type, 1)) + == TYPE_CODE_FLT))) + && tdep->mips_fpu_type != MIPS_FPU_NONE) + { + /* A struct that contains one or two floats. Each value is part + in the least significant part of their floating point + register.. */ + bfd_byte *reg = alloca (MAX_REGISTER_RAW_SIZE); + int regnum; + int field; + for (field = 0, regnum = FP0_REGNUM; + field < TYPE_NFIELDS (type); + field++, regnum += 2) + { + int offset = (FIELD_BITPOS (TYPE_FIELDS (type)[field]) + / 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)), + TARGET_BYTE_ORDER, in, out, offset); + } + } + else if (TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION) + { + /* A structure or union. Extract the left justified value, + regardless of the byte order. I.e. DO NOT USE + mips_xfer_lower. */ + int offset; + int regnum; + for (offset = 0, regnum = V0_REGNUM; + offset < TYPE_LENGTH (type); + offset += REGISTER_RAW_SIZE (regnum), regnum++) + { + int xfer = REGISTER_RAW_SIZE (regnum); + if (offset + xfer > TYPE_LENGTH (type)) + xfer = TYPE_LENGTH (type) - offset; + 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); + } } + else + { + /* A scalar extract each part but least-significant-byte + justified. */ + int offset; + int regnum; + for (offset = 0, regnum = V0_REGNUM; + offset < TYPE_LENGTH (type); + offset += REGISTER_RAW_SIZE (regnum), regnum++) + { + int xfer = REGISTER_RAW_SIZE (regnum); + int pos = 0; + if (offset + xfer > TYPE_LENGTH (type)) + xfer = TYPE_LENGTH (type) - offset; + 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); + } + } +} + +static void +mips_n32n64_extract_return_value (struct type *type, + struct regcache *regcache, + void *valbuf) +{ + mips_n32n64_xfer_return_value (type, regcache, valbuf, NULL); +} + +static void +mips_n32n64_store_return_value (struct type *type, char *valbuf) +{ + mips_n32n64_xfer_return_value (type, current_regcache, NULL, valbuf); +} + +static void +mips_store_struct_return (CORE_ADDR addr, CORE_ADDR sp) +{ + /* Nothing to do -- push_arguments does all the work. */ +} + +static CORE_ADDR +mips_extract_struct_value_address (struct regcache *regcache) +{ + /* 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. */ + LONGEST val; + + regcache_cooked_read_signed (regcache, V0_REGNUM, &val); + return val; } /* Exported procedure: Is PC in the signal trampoline code */ -int -in_sigtramp (CORE_ADDR pc, char *ignore) +static int +mips_pc_in_sigtramp (CORE_ADDR pc, char *ignore) { if (sigtramp_address == 0) fixup_sigtramp (); @@ -3419,10 +5036,7 @@ set_mipsfpu_single_command (char *args, int from_tty) { mips_fpu_type = MIPS_FPU_SINGLE; mips_fpu_type_auto = 0; - if (GDB_MULTI_ARCH) - { - gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_SINGLE; - } + gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_SINGLE; } static void @@ -3430,10 +5044,7 @@ set_mipsfpu_double_command (char *args, int from_tty) { mips_fpu_type = MIPS_FPU_DOUBLE; mips_fpu_type_auto = 0; - if (GDB_MULTI_ARCH) - { - gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_DOUBLE; - } + gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_DOUBLE; } static void @@ -3441,10 +5052,7 @@ set_mipsfpu_none_command (char *args, int from_tty) { mips_fpu_type = MIPS_FPU_NONE; mips_fpu_type_auto = 0; - if (GDB_MULTI_ARCH) - { - gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_NONE; - } + gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_NONE; } static void @@ -3487,7 +5095,7 @@ mips_show_processor_type_command (char *args, int from_tty) /* Modify the actual processor type. */ -int +static int mips_set_processor_type (char *str) { int i; @@ -3553,10 +5161,10 @@ gdb_print_insn_mips (bfd_vma memaddr, disassemble_info *info) it's definitely a 16-bit function. Otherwise, we have to just guess that if the address passed in is odd, it's 16-bits. */ if (proc_desc) - info->mach = pc_is_mips16 (PROC_LOW_ADDR (proc_desc)) ? + info->mach = pc_is_mips16 (PROC_LOW_ADDR (proc_desc)) ? bfd_mach_mips16 : TM_PRINT_INSN_MACH; else - info->mach = pc_is_mips16 (memaddr) ? + info->mach = pc_is_mips16 (memaddr) ? bfd_mach_mips16 : TM_PRINT_INSN_MACH; /* Round down the instruction address to the appropriate boundary. */ @@ -3589,7 +5197,7 @@ gdb_print_insn_mips (bfd_vma memaddr, disassemble_info *info) (if necessary) to point to the actual memory location where the breakpoint should be inserted. */ -unsigned char * +static const unsigned char * mips_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr) { if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) @@ -3671,7 +5279,7 @@ mips_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr) This function implements the SKIP_TRAMPOLINE_CODE macro. */ -CORE_ADDR +static CORE_ADDR mips_skip_stub (CORE_ADDR pc) { char *name; @@ -3754,7 +5362,7 @@ mips_skip_stub (CORE_ADDR pc) /* Return non-zero if the PC is inside a call thunk (aka stub or trampoline). This implements the IN_SOLIB_CALL_TRAMPOLINE macro. */ -int +static int mips_in_call_stub (CORE_ADDR pc, char *name) { CORE_ADDR start_addr; @@ -3782,7 +5390,7 @@ mips_in_call_stub (CORE_ADDR pc, char *name) /* Return non-zero if the PC is inside a return thunk (aka stub or trampoline). This implements the IN_SOLIB_RETURN_TRAMPOLINE macro. */ -int +static int mips_in_return_stub (CORE_ADDR pc, char *name) { CORE_ADDR start_addr; @@ -3832,7 +5440,7 @@ mips_ignore_helper (CORE_ADDR pc) point (e.g. programs in ROM) should define a symbol __CALL_DUMMY_ADDRESS whose address is the location where the breakpoint should be placed. */ -CORE_ADDR +static CORE_ADDR mips_call_dummy_address (void) { struct minimal_symbol *sym; @@ -3874,59 +5482,47 @@ mips_coerce_float_to_double (struct type *formal, struct type *actual) static void mips_get_saved_register (char *raw_buffer, - int *optimized, + int *optimizedp, CORE_ADDR *addrp, struct frame_info *frame, int regnum, - enum lval_type *lval) + enum lval_type *lvalp) { - CORE_ADDR addr; + CORE_ADDR addrx; + enum lval_type lvalx; + int optimizedx; + int realnum; if (!target_has_registers) error ("No registers."); - /* Normal systems don't optimize out things with register numbers. */ - if (optimized != NULL) - *optimized = 0; - addr = find_saved_register (frame, regnum); - if (addr != 0) + /* Make certain that all needed parameters are present. */ + if (addrp == NULL) + addrp = &addrx; + if (lvalp == NULL) + lvalp = &lvalx; + if (optimizedp == NULL) + optimizedp = &optimizedx; + frame_register_unwind (get_next_frame (frame), regnum, optimizedp, lvalp, + addrp, &realnum, 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 (lval != NULL) - *lval = lval_memory; - if (regnum == SP_REGNUM) - { - if (raw_buffer != NULL) - { - /* Put it back in target format. */ - store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), - (LONGEST) addr); - } - if (addrp != NULL) - *addrp = 0; - return; - } if (raw_buffer != NULL) { - LONGEST val; if (regnum < 32) - /* Only MIPS_SAVED_REGSIZE bytes of GP registers are - saved. */ - val = read_memory_integer (addr, MIPS_SAVED_REGSIZE); - else - val = read_memory_integer (addr, REGISTER_RAW_SIZE (regnum)); - store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), val); + { + /* Only MIPS_SAVED_REGSIZE bytes of GP registers are + saved. */ + LONGEST val = read_memory_integer ((*addrp), MIPS_SAVED_REGSIZE); + store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), val); + } } } - else - { - if (lval != NULL) - *lval = lval_register; - addr = REGISTER_BYTE (regnum); - if (raw_buffer != NULL) - read_register_gen (regnum, raw_buffer); - } - if (addrp != NULL) - *addrp = addr; } /* Immediately after a function call, return the saved pc. @@ -3949,7 +5545,7 @@ mips_stab_reg_to_regnum (int num) { if (num < 32) return num; - else + else return num + FP0_REGNUM - 38; } @@ -3978,6 +5574,47 @@ mips_integer_to_address (struct type *type, void *buf) TYPE_LENGTH (builtin_type_void_data_ptr)); } +static void +mips_find_abi_section (bfd *abfd, asection *sect, void *obj) +{ + enum mips_abi *abip = (enum mips_abi *) obj; + const char *name = bfd_get_section_name (abfd, sect); + + if (*abip != MIPS_ABI_UNKNOWN) + return; + + if (strncmp (name, ".mdebug.", 8) != 0) + return; + + if (strcmp (name, ".mdebug.abi32") == 0) + *abip = MIPS_ABI_O32; + else if (strcmp (name, ".mdebug.abiN32") == 0) + *abip = MIPS_ABI_N32; + else if (strcmp (name, ".mdebug.abi64") == 0) + *abip = MIPS_ABI_N64; + else if (strcmp (name, ".mdebug.abiO64") == 0) + *abip = MIPS_ABI_O64; + else if (strcmp (name, ".mdebug.eabi32") == 0) + *abip = MIPS_ABI_EABI32; + else if (strcmp (name, ".mdebug.eabi64") == 0) + *abip = MIPS_ABI_EABI64; + else + warning ("unsupported ABI %s.", name + 8); +} + +static enum mips_abi +global_mips_abi (void) +{ + int i; + + for (i = 0; mips_abi_strings[i] != NULL; i++) + if (mips_abi_strings[i] == mips_abi_string) + return (enum mips_abi) i; + + internal_error (__FILE__, __LINE__, + "unknown ABI string"); +} + static struct gdbarch * mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) @@ -3987,7 +5624,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch *gdbarch; struct gdbarch_tdep *tdep; int elf_flags; - enum mips_abi mips_abi; + enum mips_abi mips_abi, found_abi, wanted_abi; + enum gdb_osabi osabi = GDB_OSABI_UNKNOWN; /* Reset the disassembly info, in case it was set to something non-default. */ @@ -3995,14 +5633,20 @@ mips_gdbarch_init (struct gdbarch_info info, tm_print_insn_info.arch = bfd_arch_unknown; tm_print_insn_info.mach = 0; - /* Extract the elf_flags if available */ - if (info.abfd != NULL - && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour) - elf_flags = elf_elfheader (info.abfd)->e_flags; - else - elf_flags = 0; + elf_flags = 0; - /* Check ELF_FLAGS to see if it specifies the ABI being used. */ + if (info.abfd) + { + /* First of all, extract the elf_flags, if available. */ + if (bfd_get_flavour (info.abfd) == bfd_target_elf_flavour) + elf_flags = elf_elfheader (info.abfd)->e_flags; + + /* Try to determine the OS ABI of the object we are loading. If + we end up with `unknown', just leave it that way. */ + osabi = gdbarch_lookup_osabi (info.abfd); + } + + /* Check ELF_FLAGS to see if it specifies the ABI being used. */ switch ((elf_flags & EF_MIPS_ABI)) { case E_MIPS_ABI_O32: @@ -4025,7 +5669,16 @@ mips_gdbarch_init (struct gdbarch_info info, break; } - /* Try the architecture for any hint of the corect ABI */ + /* GCC creates a pseudo-section whose name describes the ABI. */ + if (mips_abi == MIPS_ABI_UNKNOWN && info.abfd != NULL) + bfd_map_over_sections (info.abfd, mips_find_abi_section, &mips_abi); + + /* If we have no bfd, then mips_abi will still be MIPS_ABI_UNKNOWN. + Use the ABI from the last architecture if there is one. */ + if (info.abfd == NULL && arches != NULL) + mips_abi = gdbarch_tdep (arches->gdbarch)->found_abi; + + /* Try the architecture for any hint of the correct ABI. */ if (mips_abi == MIPS_ABI_UNKNOWN && info.bfd_arch_info != NULL && info.bfd_arch_info->arch == bfd_arch_mips) @@ -4041,14 +5694,27 @@ mips_gdbarch_init (struct gdbarch_info info, break; case bfd_mach_mips8000: case bfd_mach_mips10000: - mips_abi = MIPS_ABI_N32; + /* On Irix, ELF64 executables use the N64 ABI. The + pseudo-sections which describe the ABI aren't present + on IRIX. (Even for executables created by gcc.) */ + if (bfd_get_flavour (info.abfd) == bfd_target_elf_flavour + && elf_elfheader (info.abfd)->e_ident[EI_CLASS] == ELFCLASS64) + mips_abi = MIPS_ABI_N64; + else + mips_abi = MIPS_ABI_N32; break; } } -#ifdef MIPS_DEFAULT_ABI + if (mips_abi == MIPS_ABI_UNKNOWN) - mips_abi = MIPS_DEFAULT_ABI; -#endif + mips_abi = MIPS_ABI_O32; + + /* Now that we have found what the ABI for this binary would be, + check whether the user is overriding it. */ + found_abi = mips_abi; + wanted_abi = global_mips_abi (); + if (wanted_abi != MIPS_ABI_UNKNOWN) + mips_abi = wanted_abi; if (gdbarch_debug) { @@ -4058,6 +5724,9 @@ mips_gdbarch_init (struct gdbarch_info info, fprintf_unfiltered (gdb_stdlog, "mips_gdbarch_init: mips_abi = %d\n", mips_abi); + fprintf_unfiltered (gdb_stdlog, + "mips_gdbarch_init: found_mips_abi = %d\n", + found_abi); } /* try to find a pre-existing architecture */ @@ -4066,95 +5735,129 @@ mips_gdbarch_init (struct gdbarch_info info, arches = gdbarch_list_lookup_by_info (arches->next, &info)) { /* MIPS needs to be pedantic about which ABI the object is - using. */ + using. */ if (gdbarch_tdep (arches->gdbarch)->elf_flags != elf_flags) continue; if (gdbarch_tdep (arches->gdbarch)->mips_abi != mips_abi) continue; - return arches->gdbarch; + if (gdbarch_tdep (arches->gdbarch)->osabi == osabi) + return arches->gdbarch; } - /* Need a new architecture. Fill in a target specific vector. */ + /* Need a new architecture. Fill in a target specific vector. */ tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep)); gdbarch = gdbarch_alloc (&info, tdep); tdep->elf_flags = elf_flags; + tdep->osabi = osabi; - /* Initially set everything according to the default ABI/ISA. */ + /* Initially set everything according to the default ABI/ISA. */ set_gdbarch_short_bit (gdbarch, 16); set_gdbarch_int_bit (gdbarch, 32); 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_max_register_raw_size (gdbarch, 8); + set_gdbarch_max_register_virtual_size (gdbarch, 8); + tdep->found_abi = found_abi; tdep->mips_abi = mips_abi; + set_gdbarch_elf_make_msymbol_special (gdbarch, + mips_elf_make_msymbol_special); + + if (osabi == GDB_OSABI_IRIX) + set_gdbarch_num_regs (gdbarch, 71); + else + set_gdbarch_num_regs (gdbarch, 90); + switch (mips_abi) { case MIPS_ABI_O32: - tdep->mips_abi_string = "o32"; + set_gdbarch_push_arguments (gdbarch, mips_o32_push_arguments); + set_gdbarch_deprecated_store_return_value (gdbarch, mips_o32_store_return_value); + set_gdbarch_extract_return_value (gdbarch, mips_o32_extract_return_value); 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->mips_regs_have_home_p = 1; tdep->gdb_target_is_mips64 = 0; tdep->default_mask_address_p = 0; set_gdbarch_long_bit (gdbarch, 32); set_gdbarch_ptr_bit (gdbarch, 32); set_gdbarch_long_long_bit (gdbarch, 64); + set_gdbarch_reg_struct_has_addr (gdbarch, + mips_o32_reg_struct_has_addr); + set_gdbarch_use_struct_convention (gdbarch, + mips_o32_use_struct_convention); break; case MIPS_ABI_O64: - tdep->mips_abi_string = "o64"; + set_gdbarch_push_arguments (gdbarch, mips_o64_push_arguments); + set_gdbarch_deprecated_store_return_value (gdbarch, mips_o64_store_return_value); + set_gdbarch_deprecated_extract_return_value (gdbarch, mips_o64_extract_return_value); 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->mips_regs_have_home_p = 1; tdep->gdb_target_is_mips64 = 1; - tdep->default_mask_address_p = 0; + tdep->default_mask_address_p = 0; set_gdbarch_long_bit (gdbarch, 32); set_gdbarch_ptr_bit (gdbarch, 32); set_gdbarch_long_long_bit (gdbarch, 64); + set_gdbarch_reg_struct_has_addr (gdbarch, + mips_o32_reg_struct_has_addr); + set_gdbarch_use_struct_convention (gdbarch, + mips_o32_use_struct_convention); break; case MIPS_ABI_EABI32: - tdep->mips_abi_string = "eabi32"; + set_gdbarch_push_arguments (gdbarch, mips_eabi_push_arguments); + set_gdbarch_deprecated_store_return_value (gdbarch, mips_eabi_store_return_value); + set_gdbarch_deprecated_extract_return_value (gdbarch, mips_eabi_extract_return_value); 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->mips_regs_have_home_p = 0; tdep->gdb_target_is_mips64 = 0; tdep->default_mask_address_p = 0; set_gdbarch_long_bit (gdbarch, 32); set_gdbarch_ptr_bit (gdbarch, 32); set_gdbarch_long_long_bit (gdbarch, 64); + set_gdbarch_reg_struct_has_addr (gdbarch, + mips_eabi_reg_struct_has_addr); + set_gdbarch_use_struct_convention (gdbarch, + mips_eabi_use_struct_convention); break; case MIPS_ABI_EABI64: - tdep->mips_abi_string = "eabi64"; + set_gdbarch_push_arguments (gdbarch, mips_eabi_push_arguments); + set_gdbarch_deprecated_store_return_value (gdbarch, mips_eabi_store_return_value); + set_gdbarch_deprecated_extract_return_value (gdbarch, mips_eabi_extract_return_value); 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->mips_regs_have_home_p = 0; tdep->gdb_target_is_mips64 = 1; tdep->default_mask_address_p = 0; set_gdbarch_long_bit (gdbarch, 64); set_gdbarch_ptr_bit (gdbarch, 64); set_gdbarch_long_long_bit (gdbarch, 64); + set_gdbarch_reg_struct_has_addr (gdbarch, + mips_eabi_reg_struct_has_addr); + set_gdbarch_use_struct_convention (gdbarch, + mips_eabi_use_struct_convention); break; case MIPS_ABI_N32: - tdep->mips_abi_string = "n32"; - tdep->mips_default_saved_regsize = 4; + set_gdbarch_push_arguments (gdbarch, mips_n32n64_push_arguments); + set_gdbarch_deprecated_store_return_value (gdbarch, mips_n32n64_store_return_value); + set_gdbarch_extract_return_value (gdbarch, mips_n32n64_extract_return_value); + 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->mips_regs_have_home_p = 0; - tdep->gdb_target_is_mips64 = 0; + tdep->gdb_target_is_mips64 = 1; tdep->default_mask_address_p = 0; set_gdbarch_long_bit (gdbarch, 32); set_gdbarch_ptr_bit (gdbarch, 32); @@ -4170,21 +5873,46 @@ mips_gdbarch_init (struct gdbarch_info info, tm_print_insn_info.mach = info.bfd_arch_info->mach; else tm_print_insn_info.mach = bfd_mach_mips8000; + + set_gdbarch_use_struct_convention (gdbarch, + mips_n32n64_use_struct_convention); + set_gdbarch_reg_struct_has_addr (gdbarch, + mips_n32n64_reg_struct_has_addr); break; - default: - tdep->mips_abi_string = "default"; - tdep->mips_default_saved_regsize = MIPS_REGSIZE; - tdep->mips_default_stack_argsize = MIPS_REGSIZE; - tdep->mips_fp_register_double = (REGISTER_VIRTUAL_SIZE (FP0_REGNUM) == 8); + case MIPS_ABI_N64: + set_gdbarch_push_arguments (gdbarch, mips_n32n64_push_arguments); + set_gdbarch_deprecated_store_return_value (gdbarch, mips_n32n64_store_return_value); + set_gdbarch_extract_return_value (gdbarch, mips_n32n64_extract_return_value); + 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->mips_regs_have_home_p = 1; - tdep->gdb_target_is_mips64 = 0; + tdep->gdb_target_is_mips64 = 1; tdep->default_mask_address_p = 0; - set_gdbarch_long_bit (gdbarch, 32); - set_gdbarch_ptr_bit (gdbarch, 32); + set_gdbarch_long_bit (gdbarch, 64); + set_gdbarch_ptr_bit (gdbarch, 64); set_gdbarch_long_long_bit (gdbarch, 64); + + /* Set up the disassembler info, so that we get the right + register names from libopcodes. */ + tm_print_insn_info.flavour = bfd_target_elf_flavour; + tm_print_insn_info.arch = bfd_arch_mips; + if (info.bfd_arch_info != NULL + && info.bfd_arch_info->arch == bfd_arch_mips + && info.bfd_arch_info->mach) + tm_print_insn_info.mach = info.bfd_arch_info->mach; + else + tm_print_insn_info.mach = bfd_mach_mips8000; + + set_gdbarch_use_struct_convention (gdbarch, + mips_n32n64_use_struct_convention); + set_gdbarch_reg_struct_has_addr (gdbarch, + mips_n32n64_reg_struct_has_addr); break; + default: + internal_error (__FILE__, __LINE__, + "unknown ABI in switch"); } /* FIXME: jlarmour/2000-04-07: There *is* a flag EF_MIPS_32BIT_MODE @@ -4193,9 +5921,9 @@ mips_gdbarch_init (struct gdbarch_info info, ``We deliberately don't allow "-gp32" to set the MIPS_32BITMODE flag in object files because to do so would make it impossible to - link with libraries compiled without "-gp32". This is + link with libraries compiled without "-gp32". This is unnecessarily restrictive. - + We could solve this problem by adding "-gp32" multilibs to gcc, but to set this flag before gcc is built with such multilibs will break too many systems.'' @@ -4203,10 +5931,10 @@ mips_gdbarch_init (struct gdbarch_info info, But even more unhelpfully, the default linker output target for mips64-elf is elf32-bigmips, and has EF_MIPS_32BIT_MODE set, even for 64-bit programs - you need to change the ABI to change this, - and not all gcc targets support that currently. Therefore using + and not all gcc targets support that currently. Therefore using this flag to detect 32-bit mode would do the wrong thing given the current gcc - it would make GDB treat these 64-bit programs - as 32-bit programs by default. */ + as 32-bit programs by default. */ /* enable/disable the MIPS FPU */ if (!mips_fpu_type_auto) @@ -4233,51 +5961,68 @@ mips_gdbarch_init (struct gdbarch_info info, /* MIPS version of register names. NOTE: At present the MIPS register name management is part way between the old - #undef/#define REGISTER_NAMES and the new REGISTER_NAME(nr). - Further work on it is required. */ + Further work on it is required. */ + /* NOTE: many targets (esp. embedded) do not go thru the + gdbarch_register_name vector at all, instead bypassing it + by defining REGISTER_NAMES. */ set_gdbarch_register_name (gdbarch, mips_register_name); set_gdbarch_read_pc (gdbarch, mips_read_pc); set_gdbarch_write_pc (gdbarch, generic_target_write_pc); - set_gdbarch_read_fp (gdbarch, generic_target_read_fp); - set_gdbarch_write_fp (gdbarch, generic_target_write_fp); - set_gdbarch_read_sp (gdbarch, generic_target_read_sp); + set_gdbarch_read_fp (gdbarch, mips_read_sp); /* Draft FRAME base. */ + set_gdbarch_read_sp (gdbarch, mips_read_sp); set_gdbarch_write_sp (gdbarch, generic_target_write_sp); - /* Add/remove bits from an address. The MIPS needs be careful to - ensure that all 32 bit addresses are sign extended to 64 bits. */ + /* Add/remove bits from an address. The MIPS needs be careful to + ensure that all 32 bit addresses are sign extended to 64 bits. */ set_gdbarch_addr_bits_remove (gdbarch, mips_addr_bits_remove); /* There's a mess in stack frame creation. See comments in - blockframe.c near reference to INIT_FRAME_PC_FIRST. */ - set_gdbarch_init_frame_pc_first (gdbarch, mips_init_frame_pc_first); - set_gdbarch_init_frame_pc (gdbarch, init_frame_pc_noop); + blockframe.c near reference to DEPRECATED_INIT_FRAME_PC_FIRST. */ + set_gdbarch_deprecated_init_frame_pc_first (gdbarch, mips_init_frame_pc_first); + set_gdbarch_deprecated_init_frame_pc (gdbarch, init_frame_pc_noop); - /* Map debug register numbers onto internal register numbers. */ + /* Map debug register numbers onto internal register numbers. */ set_gdbarch_stab_reg_to_regnum (gdbarch, mips_stab_reg_to_regnum); set_gdbarch_ecoff_reg_to_regnum (gdbarch, mips_ecoff_reg_to_regnum); /* Initialize a frame */ set_gdbarch_init_extra_frame_info (gdbarch, mips_init_extra_frame_info); + set_gdbarch_frame_init_saved_regs (gdbarch, mips_frame_init_saved_regs); /* MIPS version of CALL_DUMMY */ set_gdbarch_call_dummy_p (gdbarch, 1); set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0); - set_gdbarch_use_generic_dummy_frames (gdbarch, 0); - set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT); set_gdbarch_call_dummy_address (gdbarch, mips_call_dummy_address); + set_gdbarch_push_return_address (gdbarch, mips_push_return_address); + set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame); + set_gdbarch_pop_frame (gdbarch, mips_pop_frame); set_gdbarch_call_dummy_start_offset (gdbarch, 0); set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1); set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0); set_gdbarch_call_dummy_length (gdbarch, 0); - set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point); + set_gdbarch_fix_call_dummy (gdbarch, mips_fix_call_dummy); set_gdbarch_call_dummy_words (gdbarch, mips_call_dummy_words); set_gdbarch_sizeof_call_dummy_words (gdbarch, sizeof (mips_call_dummy_words)); set_gdbarch_push_return_address (gdbarch, mips_push_return_address); - set_gdbarch_push_arguments (gdbarch, mips_push_arguments); - set_gdbarch_register_convertible (gdbarch, generic_register_convertible_not); + 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_coerce_float_to_double (gdbarch, mips_coerce_float_to_double); + set_gdbarch_frame_chain (gdbarch, mips_frame_chain); set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid); + set_gdbarch_frameless_function_invocation (gdbarch, + generic_frameless_function_invocation_not); + set_gdbarch_frame_saved_pc (gdbarch, mips_frame_saved_pc); + set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown); + set_gdbarch_frame_args_skip (gdbarch, 0); + set_gdbarch_get_saved_register (gdbarch, mips_get_saved_register); set_gdbarch_inner_than (gdbarch, core_addr_lessthan); @@ -4290,9 +6035,44 @@ mips_gdbarch_init (struct gdbarch_info info, set_gdbarch_pointer_to_address (gdbarch, signed_pointer_to_address); set_gdbarch_address_to_pointer (gdbarch, address_to_signed_pointer); set_gdbarch_integer_to_address (gdbarch, mips_integer_to_address); + + 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_virtual_size (gdbarch, generic_register_size); + + set_gdbarch_deprecated_do_registers_info (gdbarch, mips_do_registers_info); + set_gdbarch_pc_in_sigtramp (gdbarch, mips_pc_in_sigtramp); + + /* Hook in OS ABI-specific overrides, if they have been registered. */ + gdbarch_init_osabi (info, gdbarch, osabi); + + set_gdbarch_store_struct_return (gdbarch, mips_store_struct_return); + set_gdbarch_extract_struct_value_address (gdbarch, + mips_extract_struct_value_address); + + set_gdbarch_skip_trampoline_code (gdbarch, mips_skip_stub); + + set_gdbarch_in_solib_call_trampoline (gdbarch, mips_in_call_stub); + set_gdbarch_in_solib_return_trampoline (gdbarch, mips_in_return_stub); + return gdbarch; } +static void +mips_abi_update (char *ignore_args, int from_tty, + struct cmd_list_element *c) +{ + struct gdbarch_info info; + + /* Force the architecture to update, and (if it's a MIPS architecture) + mips_gdbarch_init will take care of the rest. */ + gdbarch_info_init (&info); + gdbarch_update_p (info); +} + static void mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file) { @@ -4334,7 +6114,7 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file) fprintf_unfiltered (file, "mips_dump_tdep: tdep->mips_abi = %d (%s)\n", tdep->mips_abi, - tdep->mips_abi_string); + mips_abi_strings[tdep->mips_abi]); fprintf_unfiltered (file, "mips_dump_tdep: mips_mask_address_p() %d (default %d)\n", mips_mask_address_p (), @@ -4370,9 +6150,6 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file) fprintf_unfiltered (file, "mips_dump_tdep: FP_REGISTER_DOUBLE = %d\n", FP_REGISTER_DOUBLE); - fprintf_unfiltered (file, - "mips_dump_tdep: MIPS_REGS_HAVE_HOME_P = %d\n", - MIPS_REGS_HAVE_HOME_P); fprintf_unfiltered (file, "mips_dump_tdep: MIPS_DEFAULT_STACK_ARGSIZE = %d\n", MIPS_DEFAULT_STACK_ARGSIZE); @@ -4399,24 +6176,12 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file) fprintf_unfiltered (file, "mips_dump_tdep: CAUSE_REGNUM = %d\n", CAUSE_REGNUM); - fprintf_unfiltered (file, - "mips_dump_tdep: CPLUS_MARKER = %c\n", - CPLUS_MARKER); - fprintf_unfiltered (file, - "mips_dump_tdep: DEFAULT_MIPS_TYPE = %s\n", - DEFAULT_MIPS_TYPE); - fprintf_unfiltered (file, - "mips_dump_tdep: DO_REGISTERS_INFO # %s\n", - XSTRING (DO_REGISTERS_INFO)); 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: ELF_MAKE_MSYMBOL_SPECIAL # %s\n", - XSTRING (ELF_MAKE_MSYMBOL_SPECIAL (SYM, MSYM))); fprintf_unfiltered (file, "mips_dump_tdep: FCRCS_REGNUM = %d\n", FCRCS_REGNUM); @@ -4432,12 +6197,6 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file) fprintf_unfiltered (file, "mips_dump_tdep: GDB_TARGET_IS_MIPS64 = %d\n", GDB_TARGET_IS_MIPS64); - fprintf_unfiltered (file, - "mips_dump_tdep: GDB_TARGET_MASK_DISAS_PC # %s\n", - XSTRING (GDB_TARGET_MASK_DISAS_PC (PC))); - fprintf_unfiltered (file, - "mips_dump_tdep: GDB_TARGET_UNMASK_DISAS_PC # %s\n", - XSTRING (GDB_TARGET_UNMASK_DISAS_PC (PC))); fprintf_unfiltered (file, "mips_dump_tdep: GEN_REG_SAVE_MASK = %d\n", GEN_REG_SAVE_MASK); @@ -4454,9 +6213,6 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file) fprintf_unfiltered (file, "mips_dump_tdep: IGNORE_HELPER_CALL # %s\n", XSTRING (IGNORE_HELPER_CALL (PC))); - fprintf_unfiltered (file, - "mips_dump_tdep: IN_SIGTRAMP # %s\n", - XSTRING (IN_SIGTRAMP (PC, NAME))); fprintf_unfiltered (file, "mips_dump_tdep: IN_SOLIB_CALL_TRAMPOLINE # %s\n", XSTRING (IN_SOLIB_CALL_TRAMPOLINE (PC, NAME))); @@ -4516,11 +6272,6 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file) fprintf_unfiltered (file, "mips_dump_tdep: MIPS_SAVED_REGSIZE = %d\n", MIPS_SAVED_REGSIZE); - fprintf_unfiltered (file, - "mips_dump_tdep: MSYMBOL_IS_SPECIAL = function?\n"); - fprintf_unfiltered (file, - "mips_dump_tdep: MSYMBOL_SIZE # %s\n", - XSTRING (MSYMBOL_SIZE (MSYM))); fprintf_unfiltered (file, "mips_dump_tdep: OP_LDFPR = used?\n"); fprintf_unfiltered (file, @@ -4701,6 +6452,10 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file) fprintf_unfiltered (file, "mips_dump_tdep: _PROC_MAGIC_ = %d\n", _PROC_MAGIC_); + + fprintf_unfiltered (file, + "mips_dump_tdep: OS ABI = %s\n", + gdbarch_osabi_name (tdep->osabi)); } void @@ -4709,6 +6464,11 @@ _initialize_mips_tdep (void) static struct cmd_list_element *mipsfpulist = NULL; struct cmd_list_element *c; + mips_abi_string = mips_abi_strings [MIPS_ABI_UNKNOWN]; + if (MIPS_ABI_LAST + 1 + != sizeof (mips_abi_strings) / sizeof (mips_abi_strings[0])) + internal_error (__FILE__, __LINE__, "mips_abi_strings out of sync"); + gdbarch_register (bfd_arch_mips, mips_gdbarch_init, mips_dump_tdep); if (!tm_print_insn) /* Someone may have already set it */ tm_print_insn = gdb_print_insn_mips; @@ -4751,6 +6511,22 @@ This option can be set to one of:\n\ &setmipscmdlist), &showmipscmdlist); + /* Allow the user to override the ABI. */ + c = add_set_enum_cmd + ("abi", class_obscure, mips_abi_strings, &mips_abi_string, + "Set the ABI used by this program.\n" + "This option can be set to one of:\n" + " auto - the default ABI associated with the current binary\n" + " o32\n" + " o64\n" + " n32\n" + " n64\n" + " eabi32\n" + " eabi64", + &setmipscmdlist); + add_show_from_set (c, &showmipscmdlist); + set_cmd_sfunc (c, mips_abi_update); + /* Let the user turn off floating point and set the fence post for heuristic_proc_start. */ @@ -4779,21 +6555,6 @@ This option can be set to one of:\n\ "Show current use of MIPS floating-point coprocessor target.", &showlist); -#if !GDB_MULTI_ARCH - c = add_set_cmd ("processor", class_support, var_string_noescape, - (char *) &tmp_mips_processor_type, - "Set the type of MIPS processor in use.\n\ -Set this to be able to access processor-type-specific registers.\n\ -", - &setlist); - c->function.cfunc = mips_set_processor_type_command; - c = add_show_from_set (c, &showlist); - c->function.cfunc = mips_show_processor_type_command; - - tmp_mips_processor_type = xstrdup (DEFAULT_MIPS_TYPE); - mips_set_processor_type_command (xstrdup (DEFAULT_MIPS_TYPE), 0); -#endif - /* We really would like to have both "0" and "unlimited" work, but command.c doesn't deal with that. So make it a var_zinteger because the user can always use "999999" or some such for unlimited. */ @@ -4807,18 +6568,18 @@ search. The only need to set it is when debugging a stripped executable.", &setlist); /* We need to throw away the frame cache when we set this, since it might change our ability to get backtraces. */ - c->function.sfunc = reinit_frame_cache_sfunc; + set_cmd_sfunc (c, reinit_frame_cache_sfunc); add_show_from_set (c, &showlist); /* Allow the user to control whether the upper bits of 64-bit addresses should be zeroed. */ - c = add_set_auto_boolean_cmd ("mask-address", no_class, &mask_address_var, - "Set zeroing of upper 32 bits of 64-bit addresses.\n\ -Use \"on\" to enable the masking, \"off\" to disable it and \"auto\" to allow GDB to determine\n\ -the correct value.\n", - &setmipscmdlist); - add_cmd ("mask-address", no_class, show_mask_address, - "Show current mask-address value", &showmipscmdlist); + add_setshow_auto_boolean_cmd ("mask-address", no_class, &mask_address_var, "\ +Set zeroing of upper 32 bits of 64-bit addresses.\n\ +Use \"on\" to enable the masking, \"off\" to disable it and \"auto\" to \n\ +allow GDB to determine the correct value.\n", "\ +Show zeroing of upper 32 bits of 64-bit addresses.", + NULL, show_mask_address, + &setmipscmdlist, &showmipscmdlist); /* Allow the user to control the size of 32 bit registers within the raw remote packet. */ @@ -4839,4 +6600,3 @@ that would transfer 32 bits for some registers (e.g. SR, FSR) and\n\ When non-zero, mips specific debugging is enabled.", &setdebuglist), &showdebuglist); } -