Mon Jun 30 17:54:51 1997 Michael Snyder (msnyder@cleaver.cygnus.com)

* mips-tdep.c (mips_push_arguments): special-case handling for
        odd-sized struct parameters passed in registers / on stack.
This commit is contained in:
Michael Snyder 1997-07-01 00:57:19 +00:00
parent 158bda58c5
commit 781a59b28a
2 changed files with 51 additions and 29 deletions

View File

@ -1,3 +1,8 @@
Mon Jun 30 17:54:51 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
* mips-tdep.c (mips_push_arguments): special-case handling for
odd-sized struct parameters passed in registers / on stack.
Mon Jun 30 15:30:38 1997 Michael Snyder (msnyder@cleaver.cygnus.com) Mon Jun 30 15:30:38 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
* mips-tdep.c (mips_push_arguments): tweak alignment of small * mips-tdep.c (mips_push_arguments): tweak alignment of small

View File

@ -1226,7 +1226,7 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
int float_argreg; int float_argreg;
int argnum; int argnum;
int len = 0; int len = 0;
int stack_offset; int stack_offset = 0;
/* Macros to round N up or down to the next A boundary; A must be /* Macros to round N up or down to the next A boundary; A must be
a power of two. */ a power of two. */
@ -1254,11 +1254,6 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
if (struct_return) if (struct_return)
write_register (argreg++, struct_addr); write_register (argreg++, struct_addr);
/* The offset onto the stack at which we will start copying parameters
(after the registers are used up) begins at 16 in the old ABI.
This leaves room for the "home" area for register parameters. */
stack_offset = MIPS_EABI ? 0 : MIPS_REGSIZE * 4;
/* Now load as many as possible of the first arguments into /* Now load as many as possible of the first arguments into
registers, and push the rest onto the stack. Loop thru args registers, and push the rest onto the stack. Loop thru args
from first to last. */ from first to last. */
@ -1273,7 +1268,8 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
/* The EABI passes structures that do not fit in a register by /* The EABI passes structures that do not fit in a register by
reference. In all other cases, pass the structure by value. */ reference. In all other cases, pass the structure by value. */
if (typecode == TYPE_CODE_STRUCT && MIPS_EABI && len > MIPS_REGSIZE) if (MIPS_EABI && len > MIPS_REGSIZE &&
(typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
{ {
store_address (valbuf, MIPS_REGSIZE, VALUE_ADDRESS (arg)); store_address (valbuf, MIPS_REGSIZE, VALUE_ADDRESS (arg));
typecode = TYPE_CODE_PTR; typecode = TYPE_CODE_PTR;
@ -1341,10 +1337,40 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
/* Copy the argument to general registers or the stack in /* Copy the argument to general registers or the stack in
register-sized pieces. Large arguments are split between register-sized pieces. Large arguments are split between
registers and stack. */ 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_REGSIZE) &&
(len % MIPS_REGSIZE != 0));
while (len > 0) while (len > 0)
{ {
int partial_len = len < MIPS_REGSIZE ? len : MIPS_REGSIZE; int partial_len = len < MIPS_REGSIZE ? len : MIPS_REGSIZE;
if (argreg > MIPS_LAST_ARG_REGNUM || odd_sized_struct)
{
/* Write this portion of the argument to the stack. */
int longword_offset;
longword_offset = 0;
if (TARGET_BYTE_ORDER == BIG_ENDIAN)
if (MIPS_REGSIZE == 8 &&
(typecode == TYPE_CODE_INT ||
typecode == TYPE_CODE_PTR ||
typecode == TYPE_CODE_FLT) && len <= 4)
longword_offset = 4;
else if ((typecode == TYPE_CODE_STRUCT ||
typecode == TYPE_CODE_UNION) &&
TYPE_LENGTH (arg_type) < MIPS_REGSIZE)
longword_offset = MIPS_REGSIZE - len;
write_memory (sp + stack_offset + longword_offset,
val, partial_len);
}
/* Note!!! This is NOT an else clause.
Odd sized structs may go thru BOTH paths. */
if (argreg <= MIPS_LAST_ARG_REGNUM) if (argreg <= MIPS_LAST_ARG_REGNUM)
{ {
CORE_ADDR regval = extract_address (val, partial_len); CORE_ADDR regval = extract_address (val, partial_len);
@ -1375,30 +1401,21 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
if (!MIPS_EABI) if (!MIPS_EABI)
float_argreg = MIPS_LAST_FP_ARG_REGNUM + 1; float_argreg = MIPS_LAST_FP_ARG_REGNUM + 1;
} }
else
{
/* Write this portion of the argument to the stack. */
int longword_offset;
partial_len = len;
longword_offset = 0;
if (TARGET_BYTE_ORDER == BIG_ENDIAN)
if (MIPS_REGSIZE == 8 &&
(typecode == TYPE_CODE_INT ||
typecode == TYPE_CODE_PTR ||
typecode == TYPE_CODE_FLT) && len <= 4)
longword_offset = 4;
else if ((typecode == TYPE_CODE_STRUCT ||
typecode == TYPE_CODE_UNION) &&
len < MIPS_REGSIZE)
longword_offset = MIPS_REGSIZE - len;
write_memory (sp + stack_offset + longword_offset,
val, partial_len);
stack_offset += ROUND_UP (partial_len, MIPS_REGSIZE);
}
len -= partial_len; len -= partial_len;
val += partial_len; val += partial_len;
/* The offset onto the stack at which we will start
copying parameters (after the registers are used up)
begins at (4 * MIPS_REGSIZE) in the old ABI. This
leaves room for the "home" area for register parameters.
In the new EABI, the 8 register parameters do not
have "home" stack space reserved for them, so the
stack offset does not get incremented until after
we have used up the 8 parameter registers. */
if (!(MIPS_EABI && argnum < 8))
stack_offset += ROUND_UP (partial_len, MIPS_REGSIZE);
} }
} }
} }
@ -1568,7 +1585,7 @@ mips_print_register (regnum, all)
return; return;
} }
/* If an even floating pointer register, also print as double. */ /* If an even floating point register, also print as double. */
if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM+MIPS_NUMREGS if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM+MIPS_NUMREGS
&& !((regnum-FP0_REGNUM) & 1)) && !((regnum-FP0_REGNUM) & 1))
{ {