Fix bug saving vararg registers on stack in -mpowerpc64 mode.
authorFariborz Jahanian <fjahanian@gcc.gnu.org>
Fri, 14 Nov 2003 20:05:34 +0000 (20:05 +0000)
committerFariborz Jahanian <fjahanian@gcc.gnu.org>
Fri, 14 Nov 2003 20:05:34 +0000 (20:05 +0000)
Approved by: David Edelsohn.

From-SVN: r73616

gcc/config/rs6000/rs6000.c

index 5ca78420a6b81615c4ecc6fd9fef7bb23d92844b..0b2c3bdde4798ce1f72ea5b80b5b56ac30716912 100644 (file)
@@ -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));
+    }
+}
+
 \f
 /* 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.  */