mips.c (mips_va_arg): Fix calculation of osize for EABI_FLOAT_VARARGS_P.

* config/mips/mips.c (mips_va_arg): Fix calculation of osize for
	EABI_FLOAT_VARARGS_P.

From-SVN: r81625
This commit is contained in:
Richard Sandiford 2004-05-07 15:09:23 +00:00 committed by Richard Sandiford
parent 5c8a81d5a8
commit f7dbd2895e
2 changed files with 39 additions and 19 deletions

View file

@ -1,3 +1,8 @@
2004-05-07 Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips.c (mips_va_arg): Fix calculation of osize for
EABI_FLOAT_VARARGS_P.
2004-05-07 Richard Sandiford <rsandifo@redhat.com> 2004-05-07 Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips.h (ISA_HAS_BRANCHLIKELY): Remove TARGET_MIPS5500. * config/mips/mips.h (ISA_HAS_BRANCHLIKELY): Remove TARGET_MIPS5500.

View file

@ -4133,8 +4133,6 @@ mips_va_arg (tree valist, tree type)
rsize = UNITS_PER_WORD; rsize = UNITS_PER_WORD;
} }
addr_rtx = gen_reg_rtx (Pmode);
if (!EABI_FLOAT_VARARGS_P) if (!EABI_FLOAT_VARARGS_P)
{ {
/* Case of all args in a merged stack. No need to check bounds, /* Case of all args in a merged stack. No need to check bounds,
@ -4157,12 +4155,12 @@ mips_va_arg (tree valist, tree type)
/* Emit code to set addr_rtx to the valist, and postincrement /* Emit code to set addr_rtx to the valist, and postincrement
the valist by the size of the argument, rounded up to the the valist by the size of the argument, rounded up to the
next word. */ next word. Account for padding on big-endian targets. */
t = build (POSTINCREMENT_EXPR, TREE_TYPE (gpr), gpr, t = build (POSTINCREMENT_EXPR, TREE_TYPE (gpr), gpr,
size_int (rsize)); size_int (rsize));
r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL); addr_rtx = expand_expr (t, 0, Pmode, EXPAND_NORMAL);
if (r != addr_rtx) if (BYTES_BIG_ENDIAN)
emit_move_insn (addr_rtx, r); addr_rtx = plus_constant (addr_rtx, rsize - size);
/* Flush the POSTINCREMENT. */ /* Flush the POSTINCREMENT. */
emit_queue(); emit_queue();
@ -4176,6 +4174,8 @@ mips_va_arg (tree valist, tree type)
rtx lab_over = NULL_RTX, lab_false; rtx lab_over = NULL_RTX, lab_false;
HOST_WIDE_INT osize; HOST_WIDE_INT osize;
addr_rtx = gen_reg_rtx (Pmode);
f_ovfl = TYPE_FIELDS (va_list_type_node); f_ovfl = TYPE_FIELDS (va_list_type_node);
f_gtop = TREE_CHAIN (f_ovfl); f_gtop = TREE_CHAIN (f_ovfl);
f_ftop = TREE_CHAIN (f_gtop); f_ftop = TREE_CHAIN (f_gtop);
@ -4226,6 +4226,25 @@ mips_va_arg (tree valist, tree type)
each one will take up UNITS_PER_HWFPVALUE bytes, regardless each one will take up UNITS_PER_HWFPVALUE bytes, regardless
of the float's precision. */ of the float's precision. */
rsize = UNITS_PER_HWFPVALUE; rsize = UNITS_PER_HWFPVALUE;
/* Overflow arguments are padded to UNITS_PER_WORD bytes
(= PARM_BOUNDARY bits). This can be different from RSIZE
in two cases:
(1) On 32-bit targets when TYPE is a structure such as:
struct s { float f; };
Such structures are passed in paired FPRs, so RSIZE
will be 8 bytes. However, the structure only takes
up 4 bytes of memory, so OSIZE will only be 4.
(2) In combinations such as -mgp64 -msingle-float
-fshort-double. Doubles passed in registers
will then take up 4 (UNITS_PER_HWFPVALUE) bytes,
but those passed on the stack take up
UNITS_PER_WORD bytes. */
osize = MAX (GET_MODE_SIZE (TYPE_MODE (type)), UNITS_PER_WORD);
} }
else else
{ {
@ -4239,14 +4258,8 @@ mips_va_arg (tree valist, tree type)
t = build (MODIFY_EXPR, TREE_TYPE (off), off, t); t = build (MODIFY_EXPR, TREE_TYPE (off), off, t);
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
} }
osize = rsize;
} }
/* 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_HWFPVALUE 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. */ /* [2] Emit code to branch if off == 0. */
r = expand_expr (off, NULL_RTX, TYPE_MODE (TREE_TYPE (off)), r = expand_expr (off, NULL_RTX, TYPE_MODE (TREE_TYPE (off)),
@ -4254,8 +4267,12 @@ mips_va_arg (tree valist, tree type)
emit_cmp_and_jump_insns (r, const0_rtx, EQ, const1_rtx, GET_MODE (r), emit_cmp_and_jump_insns (r, const0_rtx, EQ, const1_rtx, GET_MODE (r),
1, lab_false); 1, lab_false);
/* [4] Emit code for: addr_rtx = top - off. */ /* [4] Emit code for: addr_rtx = top - off. On big endian machines,
the argument has RSIZE - SIZE bytes of leading padding. */
t = build (MINUS_EXPR, TREE_TYPE (top), top, off); t = build (MINUS_EXPR, TREE_TYPE (top), top, off);
if (BYTES_BIG_ENDIAN && rsize > size)
t = build (PLUS_EXPR, TREE_TYPE (t), t,
build_int_2 (rsize - size, 0));
r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL); r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
if (r != addr_rtx) if (r != addr_rtx)
emit_move_insn (addr_rtx, r); emit_move_insn (addr_rtx, r);
@ -4285,12 +4302,12 @@ mips_va_arg (tree valist, tree type)
/* [10, 11]. Emit code to store ovfl in addr_rtx, then /* [10, 11]. Emit code to store ovfl in addr_rtx, then
post-increment ovfl by osize. On big-endian machines, post-increment ovfl by osize. On big-endian machines,
the argument has OSIZE - RSIZE bytes of leading padding. */ the argument has OSIZE - SIZE bytes of leading padding. */
t = build (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl, t = build (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl,
size_int (osize)); size_int (osize));
if (BYTES_BIG_ENDIAN && osize > rsize) if (BYTES_BIG_ENDIAN && osize > size)
t = build (PLUS_EXPR, TREE_TYPE (t), t, t = build (PLUS_EXPR, TREE_TYPE (t), t,
build_int_2 (osize - rsize, 0)); build_int_2 (osize - size, 0));
r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL); r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
if (r != addr_rtx) if (r != addr_rtx)
emit_move_insn (addr_rtx, r); emit_move_insn (addr_rtx, r);
@ -4298,8 +4315,6 @@ mips_va_arg (tree valist, tree type)
emit_queue(); emit_queue();
emit_label (lab_over); emit_label (lab_over);
} }
if (BYTES_BIG_ENDIAN && rsize != size)
addr_rtx = plus_constant (addr_rtx, rsize - size);
if (indirect) if (indirect)
{ {
addr_rtx = force_reg (Pmode, addr_rtx); addr_rtx = force_reg (Pmode, addr_rtx);