aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@gcc.gnu.org>2003-11-14 20:05:34 +0000
committerFariborz Jahanian <fjahanian@gcc.gnu.org>2003-11-14 20:05:34 +0000
commit5985c7a6f98e57ae61caca014aa668966f29f135 (patch)
treeb3715676311e7295d9559424ffeda2afa4d54a77 /gcc
parente6d98cb0a1ac15cb463b0711a2177ef7de1f5941 (diff)
downloadgcc-5985c7a6f98e57ae61caca014aa668966f29f135.zip
gcc-5985c7a6f98e57ae61caca014aa668966f29f135.tar.gz
gcc-5985c7a6f98e57ae61caca014aa668966f29f135.tar.bz2
Fix bug saving vararg registers on stack in -mpowerpc64 mode.
Approved by: David Edelsohn. From-SVN: r73616
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/rs6000/rs6000.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 5ca7842..0b2c3bd 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -395,6 +395,7 @@ static rtx rs6000_spe_function_arg (CUMULATIVE_ARGS *,
enum machine_mode, tree);
static rtx rs6000_mixed_function_arg (CUMULATIVE_ARGS *,
enum machine_mode, tree, int);
+static void rs6000_move_block_from_reg(int regno, rtx x, int nregs);
static void setup_incoming_varargs (CUMULATIVE_ARGS *,
enum machine_mode, tree,
int *, int);
@@ -4374,6 +4375,37 @@ function_arg_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
}
return type && int_size_in_bytes (type) < 0;
}
+
+static void
+rs6000_move_block_from_reg(int regno, rtx x, int nregs)
+{
+ int i;
+ enum machine_mode reg_mode = TARGET_32BIT ? SImode : DImode;
+
+ if (nregs == 0)
+ return;
+
+ for (i = 0; i < nregs; i++)
+ {
+ rtx tem = adjust_address_nv (x, reg_mode, i*GET_MODE_SIZE(reg_mode));
+ if (reload_completed)
+ {
+ if (! strict_memory_address_p (reg_mode, XEXP (tem, 0)))
+ tem = NULL_RTX;
+ else
+ tem = simplify_gen_subreg (reg_mode, x, BLKmode,
+ i * GET_MODE_SIZE(reg_mode));
+ }
+ else
+ tem = replace_equiv_address (tem, XEXP (tem, 0));
+
+ if (tem == NULL_RTX)
+ abort ();
+
+ emit_move_insn (tem, gen_rtx_REG (reg_mode, regno + i));
+ }
+}
+
/* Perform any needed actions needed for a function that is receiving a
variable number of arguments.
@@ -4431,8 +4463,8 @@ setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
set_mem_alias_set (mem, set);
set_mem_align (mem, BITS_PER_WORD);
- move_block_from_reg (GP_ARG_MIN_REG + first_reg_offset, mem,
- GP_ARG_NUM_REG - first_reg_offset);
+ rs6000_move_block_from_reg (GP_ARG_MIN_REG + first_reg_offset, mem,
+ GP_ARG_NUM_REG - first_reg_offset);
}
/* Save FP registers if needed. */