This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: [RFA] gdbarch changes for mips_abi_n32 on Irix
- From: Michael Snyder <msnyder at redhat dot com>
- To: cagney at redhat dot com
- Cc: gdb-patches at sources dot redhat dot com, kevinb at redhat dot com
- Date: Thu, 01 Aug 2002 18:29:56 -0700
- Subject: Re: [RFA] gdbarch changes for mips_abi_n32 on Irix
- Organization: Red Hat, Inc.
- References: <200207312234.g6VMYIA12503@reddwarf.sfbay.redhat.com>
Michael Snyder wrote:
>
> Actually, these are probably not specific to Irix at all.
>
> Basically, this change implements gdbarch_reg_struct_has_addr,
> and removes the code that was implementing it inline in
> mips_push_arguments.
>
> I've only tested it on the N32 ABI, but it should not
> functionally change any others. The methods for
> O32 and O64 are empty, which also won't produce any
> change in behavior, but I or someone else can fill
> them in, if/as/when we find out what they should be.
>
> Michael
Andrew, I could break this patch down into two smaller,
functionally discrete chunks if you'd prefer.
>
> 2002-07-31 Michael Snyder <msnyder@redhat.com>
>
> * mips-tdep.c: Define new macros MIPS_NEWABI, MIPS_OLDABI
> (by analogy with MIPS_EABI).
> (mips_use_struct_convention): NEWABI (n32 and n64) use
> same scheme as EABI.
> (mips_eabi_reg_struct_has_addr, mips_newabi_reg_struct_has_addr,
> mips_oldabi_reg_struct_has_addr): New gdbarch functions.
> (mips_push_argument): Don't convert struct args to pointers.
> (mips_gdbarch_init): Set gdbarch_reg_struct_has_addr.
>
> Index: mips-tdep.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/mips-tdep.c,v
> retrieving revision 1.85
> diff -p -r1.85 mips-tdep.c
> *** mips-tdep.c 31 Jul 2002 20:26:49 -0000 1.85
> --- mips-tdep.c 31 Jul 2002 21:45:00 -0000
> *************** struct gdbarch_tdep
> *** 146,153 ****
> enum gdb_osabi osabi;
> };
>
> ! #define MIPS_EABI (gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI32 \
> ! || gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI64)
>
> #define MIPS_LAST_FP_ARG_REGNUM (gdbarch_tdep (current_gdbarch)->mips_last_fp_arg_regnum)
>
> --- 146,162 ----
> enum gdb_osabi osabi;
> };
>
> ! #define MIPS_EABI \
> ! (gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI32 \
> ! || gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI64)
> !
> ! #define MIPS_NEWABI \
> ! (gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_N32 \
> ! || gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_N64)
> !
> ! #define MIPS_OLDABI \
> ! (gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_O32 \
> ! || gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_O64)
>
> #define MIPS_LAST_FP_ARG_REGNUM (gdbarch_tdep (current_gdbarch)->mips_last_fp_arg_regnum)
>
> *************** show_mask_address (char *cmd, int from_t
> *** 531,542 ****
> int
> mips_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 */
> }
>
> /* Tell if the program counter value in MEMADDR is in a MIPS16 function. */
>
> static int
> --- 540,586 ----
> int
> mips_use_struct_convention (int gcc_p, struct type *type)
> {
> ! if (MIPS_EABI || MIPS_NEWABI)
> return (TYPE_LENGTH (type) > 2 * MIPS_SAVED_REGSIZE);
> else
> ! return 1; /* Old ABI: 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_newabi_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 && len % MIPS_SAVED_REGSIZE != 0);
> +
> + return 0;
> + }
> +
> + int
> + mips_oldabi_reg_struct_has_addr (int gcc_p, struct type *type)
> + {
> + return 0; /* FIXME: what should we do for old abi? */
> + }
> +
> +
> /* Tell if the program counter value in MEMADDR is in a MIPS16 function. */
>
> static int
> *************** mips_push_arguments (int nargs,
> *** 2427,2440 ****
> }
>
> /* 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 non-EABI processors, 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. */
> /* MIPS_EABI squeezes a struct that contains a single floating
> point value into an FP register instead of pushing it onto the
> stack. */
> --- 2471,2487 ----
> }
>
> /* Floating point arguments passed in registers have to be
> ! treated specially (and so do double fields in a struct. FIXME:)
> !
> ! 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 non-EABI processors, 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. */
> !
> /* MIPS_EABI squeezes a struct that contains a single floating
> point value into an FP register instead of pushing it onto the
> stack. */
> *************** mips_push_arguments (int nargs,
> *** 2573,2579 ****
> fprintf_unfiltered (gdb_stdlog, " @0x%lx ", (long) addr);
> for (i = 0; i < partial_len; i++)
> {
> ! fprintf_unfiltered (gdb_stdlog, "%02x", val[i] & 0xff);
> }
> }
> write_memory (addr, val, partial_len);
> --- 2622,2629 ----
> fprintf_unfiltered (gdb_stdlog, " @0x%lx ", (long) addr);
> for (i = 0; i < partial_len; i++)
> {
> ! fprintf_unfiltered (gdb_stdlog, "%02x",
> ! val[i] & 0xff);
> }
> }
> write_memory (addr, val, partial_len);
> *************** mips_push_arguments (int nargs,
> *** 2599,2611 ****
> same for integral types.
>
> Also don't do this adjustment on EABI and 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
> --- 2649,2662 ----
> same for integral types.
>
> Also don't do this adjustment on EABI and O64
> ! binaries. FIXME: comment does not agree with
> ! code, which tests for O32, not O64. MVS
>
> 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
> ! (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
> *************** mips_gdbarch_init (struct gdbarch_info i
> *** 4465,4470 ****
> --- 4518,4526 ----
> set_gdbarch_long_bit (gdbarch, 32);
> set_gdbarch_ptr_bit (gdbarch, 32);
> set_gdbarch_long_long_bit (gdbarch, 64);
> + /* Set up reg_struct_has_addr. */
> + set_gdbarch_reg_struct_has_addr (gdbarch,
> + mips_eabi_reg_struct_has_addr);
> break;
> case MIPS_ABI_EABI64:
> tdep->mips_default_saved_regsize = 8;
> *************** mips_gdbarch_init (struct gdbarch_info i
> *** 4478,4486 ****
> set_gdbarch_long_bit (gdbarch, 64);
> set_gdbarch_ptr_bit (gdbarch, 64);
> set_gdbarch_long_long_bit (gdbarch, 64);
> break;
> case MIPS_ABI_N32:
> ! tdep->mips_default_saved_regsize = 4;
> tdep->mips_default_stack_argsize = 8;
> tdep->mips_fp_register_double = 1;
> tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
> --- 4534,4545 ----
> set_gdbarch_long_bit (gdbarch, 64);
> set_gdbarch_ptr_bit (gdbarch, 64);
> set_gdbarch_long_long_bit (gdbarch, 64);
> + /* Set up reg_struct_has_addr. */
> + set_gdbarch_reg_struct_has_addr (gdbarch,
> + mips_eabi_reg_struct_has_addr);
> break;
> case MIPS_ABI_N32:
> ! 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;
> *************** mips_gdbarch_init (struct gdbarch_info i
> *** 4491,4496 ****
> --- 4550,4558 ----
> set_gdbarch_long_bit (gdbarch, 32);
> set_gdbarch_ptr_bit (gdbarch, 32);
> set_gdbarch_long_long_bit (gdbarch, 64);
> + /* Set up reg_struct_has_addr. */
> + set_gdbarch_reg_struct_has_addr (gdbarch,
> + mips_newabi_reg_struct_has_addr);
>
> /* Set up the disassembler info, so that we get the right
> register names from libopcodes. */
> *************** mips_gdbarch_init (struct gdbarch_info i
> *** 4515,4520 ****
> --- 4577,4585 ----
> set_gdbarch_long_bit (gdbarch, 64);
> set_gdbarch_ptr_bit (gdbarch, 64);
> set_gdbarch_long_long_bit (gdbarch, 64);
> + /* Set up reg_struct_has_addr. */
> + set_gdbarch_reg_struct_has_addr (gdbarch,
> + mips_newabi_reg_struct_has_addr);
>
> /* Set up the disassembler info, so that we get the right
> register names from libopcodes. */