summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2002-04-10 10:36:50 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2002-04-10 10:36:50 +0000
commit6e45d90655ca5dc88d7c0dc2abaa75f5aa7012a3 (patch)
tree95ebb9fddcd53d748828d51d46c8a9bbe1e8e66d
parenta15ce1f89ab59ebd3c1aa1f2203d8effaf91d46e (diff)
downloadppe42-gcc-6e45d90655ca5dc88d7c0dc2abaa75f5aa7012a3.tar.gz
ppe42-gcc-6e45d90655ca5dc88d7c0dc2abaa75f5aa7012a3.zip
* config/mips/mips.c (mips_va_arg): When using the struct version
of the EABI va_list, allow arguments in the register save area to take up less room than a stack argument. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@52125 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/mips/mips.c38
2 files changed, 33 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f6e47a8a8b8..5ce2348093c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2002-04-10 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/mips.c (mips_va_arg): When using the struct version
+ of the EABI va_list, allow arguments in the register save area to
+ take up less room than a stack argument.
+
2002-04-10 Richard Henderson <rth@redhat.com>
* expr.c (expand_expr) [INTEGER_CST]: Don't force into registers
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index c04b0546a53..8188c7bbc1f 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -4582,6 +4582,7 @@ mips_va_arg (valist, type)
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);
@@ -4596,7 +4597,11 @@ mips_va_arg (valist, type)
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.
+ 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:
@@ -4608,10 +4613,10 @@ mips_va_arg (valist, type)
6: }
7: else
8: {
- 9: ovfl += ((intptr_t) ovfl + rsize - 1) & -rsize;
- 10: addr_rtx = ovfl;
- 11: ovfl += rsize;
- 12: }
+ 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. */
@@ -4643,6 +4648,13 @@ mips_va_arg (valist, type)
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)),
@@ -4668,21 +4680,25 @@ mips_va_arg (valist, type)
emit_barrier ();
emit_label (lab_false);
- if (rsize > UNITS_PER_WORD)
+ if (osize > UNITS_PER_WORD)
{
- /* [9] Emit: ovfl += ((intptr_t) ovfl + rsize - 1) & -rsize. */
+ /* [9] Emit: ovfl += ((intptr_t) ovfl + osize - 1) & -osize. */
t = build (PLUS_EXPR, TREE_TYPE (ovfl), ovfl,
- build_int_2 (rsize - 1, 0));
+ build_int_2 (osize - 1, 0));
t = build (BIT_AND_EXPR, TREE_TYPE (ovfl), t,
- build_int_2 (-rsize, -1));
+ 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 rsize. */
+ 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 (rsize));
+ 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);
OpenPOWER on IntegriCloud