diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 11e50e9234104f76bb6385d67e393ef701de51c6..52c93c06661026ca6eb930d35236141baf8598e6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2005-04-12  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+	* config/sparc/sparc.h (APPLY_RESULT_SIZE): Set to 24 in 64-bit mode.
+	* config/sparc/sparc.md (untyped_call): Save the registers manually.
+
+	* config/sparc/sparc.c (legitimate_address_p): Use TARGET_ARCH32.
+
 2005-04-12  Ulrich Weigand  <uweigand@de.ibm.com>
 
 	PR middle-end/20917
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 0e053877bfbf7e3f46af848563af9fc9f06dee84..bae1b83ee21b28667cadc7cf760b335ca18b5e6f 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -3554,7 +3554,7 @@ legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
 
       /* We can't allow TFmode in 32-bit mode, because an offset greater
 	 than the alignment (8) may cause the LO_SUM to overflow.  */
-      if (mode == TFmode && !TARGET_64BIT)
+      if (mode == TFmode && TARGET_ARCH32)
 	return 0;
     }
   else if (GET_CODE (addr) == CONST_INT && SMALL_INT (addr))
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index dcdafa0923304138ecc30110b45ac47af9aef009..ae8624d076fe22c44344de6fa8e807afe0b3057a 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -1680,7 +1680,7 @@ extern char leaf_reg_remap[];
 /* Define the size of space to allocate for the return value of an
    untyped_call.  */
 
-#define APPLY_RESULT_SIZE 16
+#define APPLY_RESULT_SIZE (TARGET_ARCH64 ? 24 : 16)
 
 /* 1 if N is a possible register number for function argument passing.
    On SPARC, these are the "output" registers.  v9 also uses %f0-%f31.  */
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 88c474c98c77b0024da063b2ab602e02687be346..2073e681c0d3d02df211ad0ce650a112c4380cbd 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -7621,21 +7621,22 @@
 (define_expand "untyped_call"
   [(parallel [(call (match_operand 0 "" "")
 		    (const_int 0))
-	      (match_operand 1 "" "")
+	      (match_operand:BLK 1 "memory_operand" "")
 	      (match_operand 2 "" "")])]
   ""
 {
-  int i;
+  rtx valreg1 = gen_rtx_REG (DImode, 8);
+  rtx valreg2 = gen_rtx_REG (TARGET_ARCH64 ? TFmode : DFmode, 32);
+  rtx result = operands[1];
 
   /* Pass constm1 to indicate that it may expect a structure value, but
      we don't know what size it is.  */
   emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, constm1_rtx));
 
-  for (i = 0; i < XVECLEN (operands[2], 0); i++)
-    {
-      rtx set = XVECEXP (operands[2], 0, i);
-      emit_move_insn (SET_DEST (set), SET_SRC (set));
-    }
+  /* Save the function value registers.  */
+  emit_move_insn (adjust_address (result, DImode, 0), valreg1);
+  emit_move_insn (adjust_address (result, TARGET_ARCH64 ? TFmode : DFmode, 8),
+				  valreg2);
 
   /* The optimizer does not know that the call sets the function value
      registers we stored in the result block.  We avoid problems by