MIPS patch: fix varargs for -msingle-float -fshort-double
Richard Sandiford
rsandifo@redhat.com
Tue Apr 9 04:37:00 GMT 2002
This patch makes the EABI va-arg handler cope with sub-word
register save slots. As far as I know, they only come about
with the combination:
-mgp64 -mabi=eabi -msingle-float -fshort-double
Then each floating-point value takes up 4 bytes when stored in the
register save area, but 8 when passed on the stack (because each
stack argument is word-aligned).
Tested by setting the default ABI to EABI for mipsisa32-elf,
no regressions.
OK to install?
Richard
* config/mips/mips.c (mips_va_arg): For the full EABI va_list, let
a register save slot take up less room than a stack argument.
Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.189
diff -c -p -d -r1.189 mips.c
*** config/mips/mips.c 5 Apr 2002 08:00:32 -0000 1.189
--- config/mips/mips.c 9 Apr 2002 11:30:09 -0000
*************** mips_va_arg (valist, type)
*** 4582,4587 ****
--- 4592,4598 ----
tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
tree ovfl, top, off;
rtx lab_over = NULL_RTX, lab_false;
+ HOST_WIDE_INT osize;
f_ovfl = TYPE_FIELDS (va_list_type_node);
f_gtop = TREE_CHAIN (f_ovfl);
*************** mips_va_arg (valist, type)
*** 4596,4602 ****
TOP be the top of the register save area;
OFF be the offset from TOP of the next register;
ADDR_RTX be the address of the argument; and
! RSIZE be the number of bytes used to store the argument.
The code we want is:
--- 4607,4617 ----
TOP be the top of the register save area;
OFF be the offset from TOP of the next register;
ADDR_RTX be the address of the argument; and
! RSIZE be the number of bytes used to store the argument
! when it's in the register save area
! OSIZE be the number of bytes used to store it when it's
! in the stack overflow area
! PADDING be (BYTES_BIG_ENDIAN ? OSIZE - RSIZE : 0)
The code we want is:
*************** mips_va_arg (valist, type)
*** 4608,4617 ****
6: }
7: else
8: {
! 9: ovfl += ((intptr_t) ovfl + rsize - 1) & -rsize;
! 10: addr_rtx = ovfl;
! 11: ovfl += rsize;
! 12: }
[1] and [9] can sometimes be optimized away. */
--- 4623,4632 ----
6: }
7: else
8: {
! 9: ovfl += ((intptr_t) ovfl + osize - 1) & -osize;
! 10: addr_rtx = ovfl + PADDING;
! 11: ovfl += osize;
! 14: }
[1] and [9] can sometimes be optimized away. */
*************** mips_va_arg (valist, type)
*** 4643,4648 ****
--- 4658,4670 ----
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
}
+ /* Every overflow argument must take up at least UNITS_PER_WORD
+ bytes (= PARM_BOUNDARY bits). RSIZE can sometimes be smaller
+ than that, such as in the combination -mgp64 -msingle-float
+ -fshort-double. Doubles passed in registers will then take
+ up UNITS_PER_FPVALUE bytes, but those passed on the stack
+ take up UNITS_PER_WORD bytes. */
+ osize = MAX (rsize, UNITS_PER_WORD);
/* [2] Emit code to branch if off == 0. */
r = expand_expr (off, NULL_RTX, TYPE_MODE (TREE_TYPE (off)),
*************** mips_va_arg (valist, type)
*** 4668,4688 ****
emit_barrier ();
emit_label (lab_false);
! if (rsize > UNITS_PER_WORD)
{
! /* [9] Emit: ovfl += ((intptr_t) ovfl + rsize - 1) & -rsize. */
t = build (PLUS_EXPR, TREE_TYPE (ovfl), ovfl,
! build_int_2 (rsize - 1, 0));
t = build (BIT_AND_EXPR, TREE_TYPE (ovfl), t,
! build_int_2 (-rsize, -1));
t = build (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
/* [10, 11]. Emit code to store ovfl in addr_rtx, then
! post-increment ovfl by rsize. */
t = build (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl,
! size_int (rsize));
r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
if (r != addr_rtx)
emit_move_insn (addr_rtx, r);
--- 4690,4714 ----
emit_barrier ();
emit_label (lab_false);
! if (osize > UNITS_PER_WORD)
{
! /* [9] Emit: ovfl += ((intptr_t) ovfl + osize - 1) & -osize. */
t = build (PLUS_EXPR, TREE_TYPE (ovfl), ovfl,
! build_int_2 (osize - 1, 0));
t = build (BIT_AND_EXPR, TREE_TYPE (ovfl), t,
! build_int_2 (-osize, -1));
t = build (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
/* [10, 11]. Emit code to store ovfl in addr_rtx, then
! post-increment ovfl by osize. On big-endian machines,
! the argument has OSIZE - RSIZE bytes of leading padding. */
t = build (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl,
! size_int (osize));
! if (BYTES_BIG_ENDIAN && osize > rsize)
! t = build (PLUS_EXPR, TREE_TYPE (t), t,
! build_int_2 (osize - rsize, 0));
r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
if (r != addr_rtx)
emit_move_insn (addr_rtx, r);
More information about the Gcc-patches
mailing list