[RFA] mips_eabi_push_arguments

Michael Snyder
2002-08-14T01:12:59Z

[-- Attachment #1: Type: text/plain, Size: 12 bytes --]

As promised.

[-- Attachment #2: patch10.diff --]
[-- Type: text/plain, Size: 21544 bytes --]

2002-08-13 Michael Snyder <msnyder@redhat.com>

* mips-tdep.c (mips_push_arguments): Rename to
mips_eabi_push_arguments, and tune for EABI.
(MIPS_REGS_HAVE_HOME_P): Delete.
(struct gdbarch_tdep): Remove mips_regs_have_home_p field.
(mips_gdbarch_init): Set gdbarch push_arguments for eabi.
Delete references to mips_regs_have_home_p.

Index: mips-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-tdep.c,v
retrieving revision 1.99
diff -c -3 -p -r1.99 mips-tdep.c
*** mips-tdep.c 10 Aug 2002 01:09:10 -0000 1.99
--- mips-tdep.c 14 Aug 2002 01:08:13 -0000
*************** struct gdbarch_tdep
*** 138,144 ****
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;
--- 138,143 ----
*************** mips2_fp_compat (void)
*** 206,216 ****
MIPS_FPU_TYPE. */
#define FP_REGISTER_DOUBLE (gdbarch_tdep (current_gdbarch)->mips_fp_register_double)

- /* 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. */
-
- #define MIPS_REGS_HAVE_HOME_P (gdbarch_tdep (current_gdbarch)->mips_regs_have_home_p)
-
/* 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. */
--- 205,210 ----
*************** mips_type_needs_double_align (struct typ
*** 2450,2467 ****
#define ROUND_UP(n,a) (((n)+(a)-1) & ~((a)-1))

CORE_ADDR
! mips_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;
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);

/* First ensure that the stack and structure return address (if any)
are properly aligned. The stack has to be at least 64-bit
--- 2444,2460 ----
#define ROUND_UP(n,a) (((n)+(a)-1) & ~((a)-1))

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;
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
*************** mips_push_arguments (int nargs,
*** 2472,2502 ****
sp = ROUND_DOWN (sp, 16);
struct_addr = ROUND_DOWN (struct_addr, 16);

! /* 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. */
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_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_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
--- 2465,2495 ----
sp = ROUND_DOWN (sp, 16);
struct_addr = ROUND_DOWN (struct_addr, 16);

! /* 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. */
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_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. */
if (struct_return)
{
if (mips_debug)
fprintf_unfiltered (gdb_stdlog,
! "mips_eabi_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
*************** mips_push_arguments (int nargs,
*** 2513,2525 ****

if (mips_debug)
fprintf_unfiltered (gdb_stdlog,
! "mips_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
&& (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
{
store_address (valbuf, MIPS_SAVED_REGSIZE, VALUE_ADDRESS (arg));
--- 2506,2517 ----

if (mips_debug)
fprintf_unfiltered (gdb_stdlog,
! "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. */
! if (len > MIPS_SAVED_REGSIZE
&& (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
{
store_address (valbuf, MIPS_SAVED_REGSIZE, VALUE_ADDRESS (arg));
*************** mips_push_arguments (int nargs,
*** 2535,2542 ****
/* 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. */
if (!FP_REGISTER_DOUBLE
&& fp_register_arg_p (typecode, arg_type))
{
--- 2527,2534 ----
/* 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. */
if (!FP_REGISTER_DOUBLE
&& fp_register_arg_p (typecode, arg_type))
{
*************** mips_push_arguments (int nargs,
*** 2555,2561 ****
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. */
if (fp_register_arg_p (typecode, arg_type)
&& float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
{
--- 2547,2553 ----
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. */
if (fp_register_arg_p (typecode, arg_type)
&& float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
{
*************** mips_push_arguments (int nargs,
*** 2570,2582 ****
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);
--- 2562,2567 ----
*************** mips_push_arguments (int nargs,
*** 2584,2625 ****
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. */
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
{
--- 2569,2587 ----
fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
float_argreg, phex (regval, 4));
write_register (float_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);
}
}
else
{
*************** mips_push_arguments (int nargs,
*** 2632,2652 ****
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 (tdep->mips_abi == MIPS_ABI_O32
! && 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)
{
! /* 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",
--- 2594,2608 ----
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)
{
! /* 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",
*************** mips_push_arguments (int nargs,
*** 2701,2713 ****

/* 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
--- 2657,2671 ----

/* 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
*************** mips_push_arguments (int nargs,
*** 2719,2747 ****
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
! 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_EABI
! && 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",
--- 2677,2683 ----
same for integral types.

Also don't do this adjustment on EABI and O64
! binaries. */

if (mips_debug)
fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
*************** mips_push_arguments (int nargs,
*** 2749,2760 ****
phex (regval, MIPS_SAVED_REGSIZE));
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;
}

len -= partial_len;
--- 2685,2690 ----
*************** mips_push_arguments (int nargs,
*** 2763,2777 ****
/* 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.
-
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);
}
}
--- 2693,2702 ----
/* 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);
}
}
*************** mips_push_arguments (int nargs,
*** 2783,2788 ****
--- 2708,2715 ----
return sp;
}

+ /* N32/N64 version of push_arguments. */
+
CORE_ADDR
mips_n32n64_push_arguments (int nargs,
struct value **args,
*************** mips_n32n64_push_arguments (int nargs,
*** 2820,2826 ****
argreg = A0_REGNUM;
float_argreg = FPA0_REGNUM;

! /* the struct_return pointer occupies the first parameter-passing reg */
if (struct_return)
{
if (mips_debug)
--- 2747,2753 ----
argreg = A0_REGNUM;
float_argreg = FPA0_REGNUM;

! /* The struct_return pointer occupies the first parameter-passing reg. */
if (struct_return)
{
if (mips_debug)
*************** mips_gdbarch_init (struct gdbarch_info i
*** 4781,4787 ****
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);
--- 4708,4713 ----
*************** mips_gdbarch_init (struct gdbarch_info i
*** 4799,4805 ****
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;
set_gdbarch_long_bit (gdbarch, 32);
--- 4725,4730 ----
*************** mips_gdbarch_init (struct gdbarch_info i
*** 4811,4823 ****
mips_o32_use_struct_convention);
break;
case MIPS_ABI_EABI32:
! set_gdbarch_push_arguments (gdbarch, mips_push_arguments);
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);
--- 4736,4747 ----
mips_o32_use_struct_convention);
break;
case MIPS_ABI_EABI32:
! set_gdbarch_push_arguments (gdbarch, mips_eabi_push_arguments);
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->gdb_target_is_mips64 = 0;
tdep->default_mask_address_p = 0;
set_gdbarch_long_bit (gdbarch, 32);
*************** mips_gdbarch_init (struct gdbarch_info i
*** 4829,4841 ****
mips_eabi_use_struct_convention);
break;
case MIPS_ABI_EABI64:
! set_gdbarch_push_arguments (gdbarch, mips_push_arguments);
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);
--- 4753,4764 ----
mips_eabi_use_struct_convention);
break;
case MIPS_ABI_EABI64:
! set_gdbarch_push_arguments (gdbarch, mips_eabi_push_arguments);
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->gdb_target_is_mips64 = 1;
tdep->default_mask_address_p = 0;
set_gdbarch_long_bit (gdbarch, 64);
*************** mips_gdbarch_init (struct gdbarch_info i
*** 4853,4859 ****
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, 32);
--- 4776,4781 ----
*************** mips_gdbarch_init (struct gdbarch_info i
*** 4883,4889 ****
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);
--- 4805,4810 ----
*************** mips_dump_tdep (struct gdbarch *current_
*** 5113,5121 ****
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);
--- 5034,5039 ----