diff options
author | Alan Modra <amodra@bigpond.net.au> | 2003-05-09 06:37:25 +0000 |
---|---|---|
committer | Alan Modra <amodra@gcc.gnu.org> | 2003-05-09 16:07:25 +0930 |
commit | c6b97fac181cd452623b4208eb0c8209b6c47c71 (patch) | |
tree | 11c05a6d50d52041f7b10158a9e959b9b5d5b82c /gcc/function.c | |
parent | 8ac3815a0865eaecb5a070d1ea59f299d2c22a87 (diff) | |
download | gcc-c6b97fac181cd452623b4208eb0c8209b6c47c71.zip gcc-c6b97fac181cd452623b4208eb0c8209b6c47c71.tar.gz gcc-c6b97fac181cd452623b4208eb0c8209b6c47c71.tar.bz2 |
expr.c (move_block_from_reg): Remove "size" parm.
* expr.c (move_block_from_reg): Remove "size" parm. Localize vars.
Move code handling pieces not larger than a word to..
* function.c (assign_parms): ..here, but use change_address instead
of adjust_address and operand_subword, and expand_binop instead of
expand_shift. Adjust calls to move_block_from_reg.
* expr.h (move_block_from_reg): Update declaration.
(copy_blkmode_from_reg): Formatting.
* Makefile.in (function.o): Add $(OPTABS_H) to deps.
* config/alpha/alpha.c (alpha_setup_incoming_varargs): Adjust
move_block_from_reg calls.
* config/arc/arc.c (arc_setup_incoming_varargs): Likewise.
* config/i960/i960.c (i960_setup_incoming_varargs): Likewise.
* config/m32r/m32r.c (m32r_setup_incoming_varargs): Likewise.
* config/m88k/m88k.c (m88k_builtin_saveregsk): Likewise.
* config/mips/mips.c (mips_setup_incoming_varargs): Likewise.
* config/pa/pa.c (hppa_builtin_saveregs): Likewise.
* config/romp/romp.h (SETUP_INCOMING_VARARGS): Likewise.
* config/rs6000/rs6000.c (setup_incoming_varargs): Likewise.
* config/sh/sh.c (sh_builtin_saveregs): Likewise.
From-SVN: r66623
Diffstat (limited to 'gcc/function.c')
-rw-r--r-- | gcc/function.c | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/gcc/function.c b/gcc/function.c index f9c0e42..ba23632 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -48,6 +48,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "except.h" #include "function.h" #include "expr.h" +#include "optabs.h" #include "libfuncs.h" #include "regs.h" #include "hard-reg-set.h" @@ -4659,7 +4660,7 @@ assign_parms (fndecl) else move_block_from_reg (REGNO (entry_parm), validize_mem (stack_parm), - partial, int_size_in_bytes (TREE_TYPE (parm))); + partial); entry_parm = stack_parm; } @@ -4769,9 +4770,9 @@ assign_parms (fndecl) if (GET_CODE (entry_parm) == REG || GET_CODE (entry_parm) == PARALLEL) { - int size_stored - = CEIL_ROUND (int_size_in_bytes (TREE_TYPE (parm)), - UNITS_PER_WORD); + int size = int_size_in_bytes (TREE_TYPE (parm)); + int size_stored = CEIL_ROUND (size, UNITS_PER_WORD); + rtx mem; /* Note that we will be storing an integral number of words. So we have to be careful to ensure that we allocate an @@ -4792,16 +4793,49 @@ assign_parms (fndecl) else if (PARM_BOUNDARY % BITS_PER_WORD != 0) abort (); + mem = validize_mem (stack_parm); + /* Handle calls that pass values in multiple non-contiguous locations. The Irix 6 ABI has examples of this. */ if (GET_CODE (entry_parm) == PARALLEL) - emit_group_store (validize_mem (stack_parm), entry_parm, - int_size_in_bytes (TREE_TYPE (parm))); + emit_group_store (mem, entry_parm, size); + + /* If SIZE is that of a mode no bigger than a word, just use + that mode's store operation. */ + else if (size <= UNITS_PER_WORD) + { + enum machine_mode mode + = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0); + + if (mode != BLKmode) + { + rtx reg = gen_rtx_REG (mode, REGNO (entry_parm)); + emit_move_insn (change_address (mem, mode, 0), reg); + } + + /* Blocks smaller than a word on a BYTES_BIG_ENDIAN + machine must be aligned to the left before storing + to memory. Note that the previous test doesn't + handle all cases (e.g. SIZE == 3). */ + else if (size != UNITS_PER_WORD + && BYTES_BIG_ENDIAN) + { + rtx tem, x; + int by = (UNITS_PER_WORD - size) * BITS_PER_UNIT; + rtx reg = gen_rtx_REG (word_mode, REGNO (entry_parm)); + + x = expand_binop (word_mode, ashl_optab, reg, + GEN_INT (by), 0, 1, OPTAB_WIDEN); + tem = change_address (mem, word_mode, 0); + emit_move_insn (tem, x); + } + else + move_block_from_reg (REGNO (entry_parm), mem, + size_stored / UNITS_PER_WORD); + } else - move_block_from_reg (REGNO (entry_parm), - validize_mem (stack_parm), - size_stored / UNITS_PER_WORD, - int_size_in_bytes (TREE_TYPE (parm))); + move_block_from_reg (REGNO (entry_parm), mem, + size_stored / UNITS_PER_WORD); } SET_DECL_RTL (parm, stack_parm); } |