diff options
author | Richard Sandiford <rsandifo@redhat.com> | 2002-04-10 10:36:50 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2002-04-10 10:36:50 +0000 |
commit | bf6d4777dd707abe911a04ec9f050a26d41fdd5b (patch) | |
tree | 95ebb9fddcd53d748828d51d46c8a9bbe1e8e66d /gcc | |
parent | ba3307c092fce730120657ab5c89ff4d0936244e (diff) | |
download | gcc-bf6d4777dd707abe911a04ec9f050a26d41fdd5b.zip gcc-bf6d4777dd707abe911a04ec9f050a26d41fdd5b.tar.gz gcc-bf6d4777dd707abe911a04ec9f050a26d41fdd5b.tar.bz2 |
mips.c (mips_va_arg): When using the struct version of the EABI va_list...
* 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.
From-SVN: r52125
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 38 |
2 files changed, 33 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f6e47a8..5ce2348 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 c04b054..8188c7b 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); |