summaryrefslogtreecommitdiffstats
path: root/recipes/gcc
diff options
context:
space:
mode:
authorKhem Raj <raj.khem@gmail.com>2009-10-06 15:29:34 -0700
committerKhem Raj <raj.khem@gmail.com>2009-10-06 15:31:34 -0700
commit84011b0d22f56008f5fd7f9c53a0e34d5861e50d (patch)
treeeb993a5c387fe0239a5a8f3befcdac9d7abbe365 /recipes/gcc
parent44943f01becfb8e61bcaeb40f47e2fd64552b276 (diff)
downloadopenembedded-84011b0d22f56008f5fd7f9c53a0e34d5861e50d.tar.gz
gcc-4.4.1: Backport powerpc patches to improve code generation at -Os
* This also fixes the u-boot build errors we get with gcc 4.4 Signed-off-by: Khem Raj <raj.khem@gmail.com>
Diffstat (limited to 'recipes/gcc')
-rw-r--r--recipes/gcc/gcc-4.4.1.inc5
-rw-r--r--recipes/gcc/gcc-4.4.1/gcc-ppc_add_d_constraint.patch1216
-rw-r--r--recipes/gcc/gcc-4.4.1/gcc-ppc_single_precision_regs.patch60
-rw-r--r--recipes/gcc/gcc-4.4.1/gcc-pr41175.patch1172
4 files changed, 2452 insertions, 1 deletions
diff --git a/recipes/gcc/gcc-4.4.1.inc b/recipes/gcc/gcc-4.4.1.inc
index f32f749ce6..9b47127486 100644
--- a/recipes/gcc/gcc-4.4.1.inc
+++ b/recipes/gcc/gcc-4.4.1.inc
@@ -7,7 +7,7 @@ LICENSE = "GPLv3"
DEPENDS = "mpfr gmp"
-INC_PR = "r5"
+INC_PR = "r6"
FILESPATHPKG .= ":gcc-$PV"
@@ -20,6 +20,9 @@ SRC_URI = "${GNU_MIRROR}/gcc/gcc-${PV}/gcc-${PV}.tar.bz2 \
file://gcc-improve-tls-macro.patch;patch=1 \
file://cache-amnesia.patch;patch=1 \
file://gcc-flags-for-build.patch;patch=1 \
+ file://gcc-ppc_single_precision_regs.patch;patch=1 \
+ file://gcc-ppc_add_d_constraint.patch;patch=1 \
+ file://gcc-pr41175.patch;patch=1 \
"
# Language Overrides
FORTRAN = ""
diff --git a/recipes/gcc/gcc-4.4.1/gcc-ppc_add_d_constraint.patch b/recipes/gcc/gcc-4.4.1/gcc-ppc_add_d_constraint.patch
new file mode 100644
index 0000000000..5e1da1ad09
--- /dev/null
+++ b/recipes/gcc/gcc-4.4.1/gcc-ppc_add_d_constraint.patch
@@ -0,0 +1,1216 @@
+Index: gcc-4.4.1/gcc/doc/md.texi
+===================================================================
+--- gcc-4.4.1.orig/gcc/doc/md.texi 2009-10-06 14:08:35.847313399 -0700
++++ gcc-4.4.1/gcc/doc/md.texi 2009-10-06 14:09:12.087313658 -0700
+@@ -1901,8 +1901,11 @@ Any constant whose absolute value is no
+ @item b
+ Address base register
+
++@item d
++Floating point register (containing 64-bit value)
++
+ @item f
+-Floating point register
++Floating point register (containing 32-bit value)
+
+ @item v
+ Vector register
+Index: gcc-4.4.1/gcc/config/rs6000/constraints.md
+===================================================================
+--- gcc-4.4.1.orig/gcc/config/rs6000/constraints.md 2009-10-06 14:08:35.827340958 -0700
++++ gcc-4.4.1/gcc/config/rs6000/constraints.md 2009-10-06 14:09:12.087313658 -0700
+@@ -23,6 +23,10 @@
+ ? FLOAT_REGS : NO_REGS"
+ "@internal")
+
++(define_register_constraint "d" "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
++ ? FLOAT_REGS : NO_REGS"
++ "@internal")
++
+ (define_register_constraint "b" "BASE_REGS"
+ "@internal")
+
+Index: gcc-4.4.1/gcc/config/rs6000/dfp.md
+===================================================================
+--- gcc-4.4.1.orig/gcc/config/rs6000/dfp.md 2009-10-06 14:08:35.797315564 -0700
++++ gcc-4.4.1/gcc/config/rs6000/dfp.md 2009-10-06 14:09:12.087313658 -0700
+@@ -105,7 +105,7 @@
+
+ (define_insn "movsd_store"
+ [(set (match_operand:DD 0 "nonimmediate_operand" "=m")
+- (unspec:DD [(match_operand:SD 1 "input_operand" "f")]
++ (unspec:DD [(match_operand:SD 1 "input_operand" "d")]
+ UNSPEC_MOVSD_STORE))]
+ "(gpc_reg_operand (operands[0], DDmode)
+ || gpc_reg_operand (operands[1], SDmode))
+@@ -128,15 +128,15 @@
+ ;; Hardware support for decimal floating point operations.
+
+ (define_insn "extendsddd2"
+- [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
++ [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
+ (float_extend:DD (match_operand:SD 1 "gpc_reg_operand" "f")))]
+ "TARGET_DFP"
+ "dctdp %0,%1"
+ [(set_attr "type" "fp")])
+
+ (define_expand "extendsdtd2"
+- [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
+- (float_extend:TD (match_operand:SD 1 "gpc_reg_operand" "f")))]
++ [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
++ (float_extend:TD (match_operand:SD 1 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ {
+ rtx tmp = gen_reg_rtx (DDmode);
+@@ -147,7 +147,7 @@
+
+ (define_insn "truncddsd2"
+ [(set (match_operand:SD 0 "gpc_reg_operand" "=f")
+- (float_truncate:SD (match_operand:DD 1 "gpc_reg_operand" "f")))]
++ (float_truncate:SD (match_operand:DD 1 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ "drsp %0,%1"
+ [(set_attr "type" "fp")])
+@@ -159,8 +159,8 @@
+ "")
+
+ (define_insn "*negdd2_fpr"
+- [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
+- (neg:DD (match_operand:DD 1 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
++ (neg:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
+ "fneg %0,%1"
+ [(set_attr "type" "fp")])
+@@ -172,15 +172,15 @@
+ "")
+
+ (define_insn "*absdd2_fpr"
+- [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
+- (abs:DD (match_operand:DD 1 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
++ (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
+ "fabs %0,%1"
+ [(set_attr "type" "fp")])
+
+ (define_insn "*nabsdd2_fpr"
+- [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
+- (neg:DD (abs:DD (match_operand:DF 1 "gpc_reg_operand" "f"))))]
++ [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
++ (neg:DD (abs:DD (match_operand:DF 1 "gpc_reg_operand" "d"))))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
+ "fnabs %0,%1"
+ [(set_attr "type" "fp")])
+@@ -281,8 +281,8 @@
+ ;; The "??" is a kludge until we can figure out a more reasonable way
+ ;; of handling these non-offsettable values.
+ (define_insn "*movdd_hardfloat32"
+- [(set (match_operand:DD 0 "nonimmediate_operand" "=!r,??r,m,f,f,m,!r,!r,!r")
+- (match_operand:DD 1 "input_operand" "r,m,r,f,m,f,G,H,F"))]
++ [(set (match_operand:DD 0 "nonimmediate_operand" "=!r,??r,m,d,d,m,!r,!r,!r")
++ (match_operand:DD 1 "input_operand" "r,m,r,d,m,d,G,H,F"))]
+ "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS
+ && (gpc_reg_operand (operands[0], DDmode)
+ || gpc_reg_operand (operands[1], DDmode))"
+@@ -417,8 +417,8 @@
+ ; ld/std require word-aligned displacements -> 'Y' constraint.
+ ; List Y->r and r->Y before r->r for reload.
+ (define_insn "*movdd_hardfloat64_mfpgpr"
+- [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,*c*l,!r,*h,!r,!r,!r,r,f")
+- (match_operand:DD 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F,f,r"))]
++ [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,d,d,m,*c*l,!r,*h,!r,!r,!r,r,d")
++ (match_operand:DD 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F,d,r"))]
+ "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
+ && (gpc_reg_operand (operands[0], DDmode)
+ || gpc_reg_operand (operands[1], DDmode))"
+@@ -443,8 +443,8 @@
+ ; ld/std require word-aligned displacements -> 'Y' constraint.
+ ; List Y->r and r->Y before r->r for reload.
+ (define_insn "*movdd_hardfloat64"
+- [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,*c*l,!r,*h,!r,!r,!r")
+- (match_operand:DD 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F"))]
++ [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,d,d,m,*c*l,!r,*h,!r,!r,!r")
++ (match_operand:DD 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F"))]
+ "TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
+ && (gpc_reg_operand (operands[0], DDmode)
+ || gpc_reg_operand (operands[1], DDmode))"
+@@ -490,8 +490,8 @@
+ "")
+
+ (define_insn "*negtd2_fpr"
+- [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
+- (neg:TD (match_operand:TD 1 "gpc_reg_operand" "f")))]
++ [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
++ (neg:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
+ "fneg %0,%1"
+ [(set_attr "type" "fp")])
+@@ -503,15 +503,15 @@
+ "")
+
+ (define_insn "*abstd2_fpr"
+- [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
+- (abs:TD (match_operand:TD 1 "gpc_reg_operand" "f")))]
++ [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
++ (abs:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
+ "fabs %0,%1"
+ [(set_attr "type" "fp")])
+
+ (define_insn "*nabstd2_fpr"
+- [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
+- (neg:TD (abs:TD (match_operand:DF 1 "gpc_reg_operand" "f"))))]
++ [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
++ (neg:TD (abs:TD (match_operand:DF 1 "gpc_reg_operand" "d"))))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
+ "fnabs %0,%1"
+ [(set_attr "type" "fp")])
+@@ -526,8 +526,8 @@
+ ; otherwise reload, given m->f, will try to pick f->f and reload it,
+ ; which doesn't make progress. Likewise r->Y must be before r->r.
+ (define_insn_and_split "*movtd_internal"
+- [(set (match_operand:TD 0 "nonimmediate_operand" "=o,f,f,r,Y,r")
+- (match_operand:TD 1 "input_operand" "f,o,f,YGHF,r,r"))]
++ [(set (match_operand:TD 0 "nonimmediate_operand" "=o,d,d,r,Y,r")
++ (match_operand:TD 1 "input_operand" "d,o,d,YGHF,r,r"))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS
+ && (gpc_reg_operand (operands[0], TDmode)
+ || gpc_reg_operand (operands[1], TDmode))"
+@@ -540,8 +540,8 @@
+ ;; Hardware support for decimal floating point operations.
+
+ (define_insn "extendddtd2"
+- [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
+- (float_extend:TD (match_operand:DD 1 "gpc_reg_operand" "f")))]
++ [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
++ (float_extend:TD (match_operand:DD 1 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ "dctqpq %0,%1"
+ [(set_attr "type" "fp")])
+@@ -552,96 +552,96 @@
+ ;; that the result is the first of the pair receiving the result of drdpq.
+
+ (define_insn "trunctddd2"
+- [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
+- (float_truncate:DD (match_operand:TD 1 "gpc_reg_operand" "f")))
+- (clobber (match_scratch:TD 2 "=f"))]
++ [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
++ (float_truncate:DD (match_operand:TD 1 "gpc_reg_operand" "d")))
++ (clobber (match_scratch:TD 2 "=d"))]
+ "TARGET_DFP"
+ "drdpq %2,%1\;fmr %0,%2"
+ [(set_attr "type" "fp")])
+
+ (define_insn "adddd3"
+- [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
+- (plus:DD (match_operand:DD 1 "gpc_reg_operand" "%f")
+- (match_operand:DD 2 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
++ (plus:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
++ (match_operand:DD 2 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ "dadd %0,%1,%2"
+ [(set_attr "type" "fp")])
+
+ (define_insn "addtd3"
+- [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
+- (plus:TD (match_operand:TD 1 "gpc_reg_operand" "%f")
+- (match_operand:TD 2 "gpc_reg_operand" "f")))]
++ [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
++ (plus:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
++ (match_operand:TD 2 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ "daddq %0,%1,%2"
+ [(set_attr "type" "fp")])
+
+ (define_insn "subdd3"
+- [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
+- (minus:DD (match_operand:DD 1 "gpc_reg_operand" "f")
+- (match_operand:DD 2 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
++ (minus:DD (match_operand:DD 1 "gpc_reg_operand" "d")
++ (match_operand:DD 2 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ "dsub %0,%1,%2"
+ [(set_attr "type" "fp")])
+
+ (define_insn "subtd3"
+- [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
+- (minus:TD (match_operand:TD 1 "gpc_reg_operand" "f")
+- (match_operand:TD 2 "gpc_reg_operand" "f")))]
++ [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
++ (minus:TD (match_operand:TD 1 "gpc_reg_operand" "d")
++ (match_operand:TD 2 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ "dsubq %0,%1,%2"
+ [(set_attr "type" "fp")])
+
+ (define_insn "muldd3"
+- [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
+- (mult:DD (match_operand:DD 1 "gpc_reg_operand" "%f")
+- (match_operand:DD 2 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
++ (mult:DD (match_operand:DD 1 "gpc_reg_operand" "%d")
++ (match_operand:DD 2 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ "dmul %0,%1,%2"
+ [(set_attr "type" "fp")])
+
+ (define_insn "multd3"
+- [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
+- (mult:TD (match_operand:TD 1 "gpc_reg_operand" "%f")
+- (match_operand:TD 2 "gpc_reg_operand" "f")))]
++ [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
++ (mult:TD (match_operand:TD 1 "gpc_reg_operand" "%d")
++ (match_operand:TD 2 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ "dmulq %0,%1,%2"
+ [(set_attr "type" "fp")])
+
+ (define_insn "divdd3"
+- [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
+- (div:DD (match_operand:DD 1 "gpc_reg_operand" "f")
+- (match_operand:DD 2 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
++ (div:DD (match_operand:DD 1 "gpc_reg_operand" "d")
++ (match_operand:DD 2 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ "ddiv %0,%1,%2"
+ [(set_attr "type" "fp")])
+
+ (define_insn "divtd3"
+- [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
+- (div:TD (match_operand:TD 1 "gpc_reg_operand" "f")
+- (match_operand:TD 2 "gpc_reg_operand" "f")))]
++ [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
++ (div:TD (match_operand:TD 1 "gpc_reg_operand" "d")
++ (match_operand:TD 2 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ "ddivq %0,%1,%2"
+ [(set_attr "type" "fp")])
+
+ (define_insn "*cmpdd_internal1"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+- (compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "f")
+- (match_operand:DD 2 "gpc_reg_operand" "f")))]
++ (compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "d")
++ (match_operand:DD 2 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ "dcmpu %0,%1,%2"
+ [(set_attr "type" "fpcompare")])
+
+ (define_insn "*cmptd_internal1"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+- (compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "f")
+- (match_operand:TD 2 "gpc_reg_operand" "f")))]
++ (compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "d")
++ (match_operand:TD 2 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ "dcmpuq %0,%1,%2"
+ [(set_attr "type" "fpcompare")])
+
+ (define_insn "floatditd2"
+- [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
+- (float:TD (match_operand:DI 1 "gpc_reg_operand" "f")))]
++ [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
++ (float:TD (match_operand:DI 1 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ "dcffixq %0,%1"
+ [(set_attr "type" "fp")])
+@@ -650,8 +650,8 @@
+ ;; This is the first stage of converting it to an integer type.
+
+ (define_insn "ftruncdd2"
+- [(set (match_operand:DD 0 "gpc_reg_operand" "=f")
+- (fix:DD (match_operand:DD 1 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DD 0 "gpc_reg_operand" "=d")
++ (fix:DD (match_operand:DD 1 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ "drintn. 0,%0,%1,1"
+ [(set_attr "type" "fp")])
+@@ -660,8 +660,8 @@
+ ;; This is the second stage of converting decimal float to integer type.
+
+ (define_insn "fixdddi2"
+- [(set (match_operand:DI 0 "gpc_reg_operand" "=f")
+- (fix:DI (match_operand:DD 1 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
++ (fix:DI (match_operand:DD 1 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ "dctfix %0,%1"
+ [(set_attr "type" "fp")])
+@@ -670,8 +670,8 @@
+ ;; This is the first stage of converting it to an integer type.
+
+ (define_insn "ftrunctd2"
+- [(set (match_operand:TD 0 "gpc_reg_operand" "=f")
+- (fix:TD (match_operand:TD 1 "gpc_reg_operand" "f")))]
++ [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
++ (fix:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ "drintnq. 0,%0,%1,1"
+ [(set_attr "type" "fp")])
+@@ -680,8 +680,8 @@
+ ;; This is the second stage of converting decimal float to integer type.
+
+ (define_insn "fixtddi2"
+- [(set (match_operand:DI 0 "gpc_reg_operand" "=f")
+- (fix:DI (match_operand:TD 1 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
++ (fix:DI (match_operand:TD 1 "gpc_reg_operand" "d")))]
+ "TARGET_DFP"
+ "dctfixq %0,%1"
+ [(set_attr "type" "fp")])
+Index: gcc-4.4.1/gcc/config/rs6000/rs6000.md
+===================================================================
+--- gcc-4.4.1.orig/gcc/config/rs6000/rs6000.md 2009-10-06 14:09:04.737313663 -0700
++++ gcc-4.4.1/gcc/config/rs6000/rs6000.md 2009-10-06 14:09:12.087313658 -0700
+@@ -5119,7 +5119,7 @@
+ "")
+
+ (define_insn_and_split "*extendsfdf2_fpr"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f,?f,f")
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d")
+ (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "@
+@@ -5142,7 +5142,7 @@
+
+ (define_insn "*truncdfsf2_fpr"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+- (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "f")))]
++ (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "frsp %0,%1"
+ [(set_attr "type" "fp")])
+@@ -5616,7 +5616,7 @@
+
+ (define_insn "*fseldfsf4"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+- (if_then_else:SF (ge (match_operand:DF 1 "gpc_reg_operand" "f")
++ (if_then_else:SF (ge (match_operand:DF 1 "gpc_reg_operand" "d")
+ (match_operand:DF 4 "zero_fp_constant" "F"))
+ (match_operand:SF 2 "gpc_reg_operand" "f")
+ (match_operand:SF 3 "gpc_reg_operand" "f")))]
+@@ -5631,8 +5631,8 @@
+ "")
+
+ (define_insn "*negdf2_fpr"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (neg:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (neg:DF (match_operand:DF 1 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "fneg %0,%1"
+ [(set_attr "type" "fp")])
+@@ -5644,15 +5644,15 @@
+ "")
+
+ (define_insn "*absdf2_fpr"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (abs:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (abs:DF (match_operand:DF 1 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "fabs %0,%1"
+ [(set_attr "type" "fp")])
+
+ (define_insn "*nabsdf2_fpr"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (neg:DF (abs:DF (match_operand:DF 1 "gpc_reg_operand" "f"))))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (neg:DF (abs:DF (match_operand:DF 1 "gpc_reg_operand" "d"))))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "fnabs %0,%1"
+ [(set_attr "type" "fp")])
+@@ -5665,9 +5665,9 @@
+ "")
+
+ (define_insn "*adddf3_fpr"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (plus:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+- (match_operand:DF 2 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (plus:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
++ (match_operand:DF 2 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "{fa|fadd} %0,%1,%2"
+ [(set_attr "type" "fp")
+@@ -5681,9 +5681,9 @@
+ "")
+
+ (define_insn "*subdf3_fpr"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (minus:DF (match_operand:DF 1 "gpc_reg_operand" "f")
+- (match_operand:DF 2 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (minus:DF (match_operand:DF 1 "gpc_reg_operand" "d")
++ (match_operand:DF 2 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "{fs|fsub} %0,%1,%2"
+ [(set_attr "type" "fp")
+@@ -5697,9 +5697,9 @@
+ "")
+
+ (define_insn "*muldf3_fpr"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+- (match_operand:DF 2 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
++ (match_operand:DF 2 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "{fm|fmul} %0,%1,%2"
+ [(set_attr "type" "dmul")
+@@ -5715,17 +5715,17 @@
+ "")
+
+ (define_insn "*divdf3_fpr"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (div:DF (match_operand:DF 1 "gpc_reg_operand" "f")
+- (match_operand:DF 2 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (div:DF (match_operand:DF 1 "gpc_reg_operand" "d")
++ (match_operand:DF 2 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !TARGET_SIMPLE_FPU"
+ "{fd|fdiv} %0,%1,%2"
+ [(set_attr "type" "ddiv")])
+
+ (define_expand "recipdf3"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")
+- (match_operand:DF 2 "gpc_reg_operand" "f")]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")
++ (match_operand:DF 2 "gpc_reg_operand" "d")]
+ UNSPEC_FRES))]
+ "TARGET_RECIP && TARGET_HARD_FLOAT && TARGET_POPCNTB && !optimize_size
+ && flag_finite_math_only && !flag_trapping_math"
+@@ -5735,37 +5735,37 @@
+ })
+
+ (define_insn "fred"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRES))]
+ "TARGET_POPCNTB && flag_finite_math_only"
+ "fre %0,%1"
+ [(set_attr "type" "fp")])
+
+ (define_insn ""
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+- (match_operand:DF 2 "gpc_reg_operand" "f"))
+- (match_operand:DF 3 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
++ (match_operand:DF 2 "gpc_reg_operand" "d"))
++ (match_operand:DF 3 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT"
+ "{fma|fmadd} %0,%1,%2,%3"
+ [(set_attr "type" "dmul")
+ (set_attr "fp_type" "fp_maddsub_d")])
+
+ (define_insn ""
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+- (match_operand:DF 2 "gpc_reg_operand" "f"))
+- (match_operand:DF 3 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
++ (match_operand:DF 2 "gpc_reg_operand" "d"))
++ (match_operand:DF 3 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT"
+ "{fms|fmsub} %0,%1,%2,%3"
+ [(set_attr "type" "dmul")
+ (set_attr "fp_type" "fp_maddsub_d")])
+
+ (define_insn ""
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (neg:DF (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+- (match_operand:DF 2 "gpc_reg_operand" "f"))
+- (match_operand:DF 3 "gpc_reg_operand" "f"))))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (neg:DF (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
++ (match_operand:DF 2 "gpc_reg_operand" "d"))
++ (match_operand:DF 3 "gpc_reg_operand" "d"))))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT
+ && HONOR_SIGNED_ZEROS (DFmode)"
+ "{fnma|fnmadd} %0,%1,%2,%3"
+@@ -5773,10 +5773,10 @@
+ (set_attr "fp_type" "fp_maddsub_d")])
+
+ (define_insn ""
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (minus:DF (mult:DF (neg:DF (match_operand:DF 1 "gpc_reg_operand" "f"))
+- (match_operand:DF 2 "gpc_reg_operand" "f"))
+- (match_operand:DF 3 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (minus:DF (mult:DF (neg:DF (match_operand:DF 1 "gpc_reg_operand" "d"))
++ (match_operand:DF 2 "gpc_reg_operand" "d"))
++ (match_operand:DF 3 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT
+ && ! HONOR_SIGNED_ZEROS (DFmode)"
+ "{fnma|fnmadd} %0,%1,%2,%3"
+@@ -5784,10 +5784,10 @@
+ (set_attr "fp_type" "fp_maddsub_d")])
+
+ (define_insn ""
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (neg:DF (minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+- (match_operand:DF 2 "gpc_reg_operand" "f"))
+- (match_operand:DF 3 "gpc_reg_operand" "f"))))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (neg:DF (minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
++ (match_operand:DF 2 "gpc_reg_operand" "d"))
++ (match_operand:DF 3 "gpc_reg_operand" "d"))))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT
+ && HONOR_SIGNED_ZEROS (DFmode)"
+ "{fnms|fnmsub} %0,%1,%2,%3"
+@@ -5795,10 +5795,10 @@
+ (set_attr "fp_type" "fp_maddsub_d")])
+
+ (define_insn ""
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (minus:DF (match_operand:DF 3 "gpc_reg_operand" "f")
+- (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+- (match_operand:DF 2 "gpc_reg_operand" "f"))))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (minus:DF (match_operand:DF 3 "gpc_reg_operand" "d")
++ (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
++ (match_operand:DF 2 "gpc_reg_operand" "d"))))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT
+ && ! HONOR_SIGNED_ZEROS (DFmode)"
+ "{fnms|fnmsub} %0,%1,%2,%3"
+@@ -5806,8 +5806,8 @@
+ (set_attr "fp_type" "fp_maddsub_d")])
+
+ (define_insn "sqrtdf2"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "d")))]
+ "(TARGET_PPC_GPOPT || TARGET_POWER2) && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_DOUBLE_FLOAT"
+ "fsqrt %0,%1"
+@@ -5865,21 +5865,21 @@
+ }")
+
+ (define_insn "*fseldfdf4"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "f")
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "d")
+ (match_operand:DF 4 "zero_fp_constant" "F"))
+- (match_operand:DF 2 "gpc_reg_operand" "f")
+- (match_operand:DF 3 "gpc_reg_operand" "f")))]
++ (match_operand:DF 2 "gpc_reg_operand" "d")
++ (match_operand:DF 3 "gpc_reg_operand" "d")))]
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "fsel %0,%1,%2,%3"
+ [(set_attr "type" "fp")])
+
+ (define_insn "*fselsfdf4"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
+ (if_then_else:DF (ge (match_operand:SF 1 "gpc_reg_operand" "f")
+ (match_operand:SF 4 "zero_fp_constant" "F"))
+- (match_operand:DF 2 "gpc_reg_operand" "f")
+- (match_operand:DF 3 "gpc_reg_operand" "f")))]
++ (match_operand:DF 2 "gpc_reg_operand" "d")
++ (match_operand:DF 3 "gpc_reg_operand" "d")))]
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_SINGLE_FLOAT"
+ "fsel %0,%1,%2,%3"
+ [(set_attr "type" "fp")])
+@@ -5935,12 +5935,12 @@
+ }")
+
+ (define_insn_and_split "*floatsidf2_internal"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=&f")
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=&d")
+ (float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))
+ (use (match_operand:SI 2 "gpc_reg_operand" "r"))
+- (use (match_operand:DF 3 "gpc_reg_operand" "f"))
++ (use (match_operand:DF 3 "gpc_reg_operand" "d"))
+ (clobber (match_operand:DF 4 "offsettable_mem_operand" "=o"))
+- (clobber (match_operand:DF 5 "gpc_reg_operand" "=&f"))
++ (clobber (match_operand:DF 5 "gpc_reg_operand" "=&d"))
+ (clobber (match_operand:SI 6 "gpc_reg_operand" "=&r"))]
+ "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "#"
+@@ -6003,12 +6003,12 @@
+ }")
+
+ (define_insn_and_split "*floatunssidf2_internal"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=&f")
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=&d")
+ (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))
+ (use (match_operand:SI 2 "gpc_reg_operand" "r"))
+- (use (match_operand:DF 3 "gpc_reg_operand" "f"))
++ (use (match_operand:DF 3 "gpc_reg_operand" "d"))
+ (clobber (match_operand:DF 4 "offsettable_mem_operand" "=o"))
+- (clobber (match_operand:DF 5 "gpc_reg_operand" "=&f"))]
++ (clobber (match_operand:DF 5 "gpc_reg_operand" "=&d"))]
+ "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "#"
+ "&& (can_create_pseudo_p () || offsettable_nonstrict_memref_p (operands[4]))"
+@@ -6072,8 +6072,8 @@
+
+ (define_insn_and_split "*fix_truncdfsi2_internal"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+- (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f")))
+- (clobber (match_operand:DI 2 "gpc_reg_operand" "=f"))
++ (fix:SI (match_operand:DF 1 "gpc_reg_operand" "d")))
++ (clobber (match_operand:DI 2 "gpc_reg_operand" "=d"))
+ (clobber (match_operand:DI 3 "offsettable_mem_operand" "=o"))]
+ "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_DOUBLE_FLOAT"
+@@ -6095,8 +6095,8 @@
+
+ (define_insn_and_split "fix_truncdfsi2_internal_gfxopt"
+ [(set (match_operand:SI 0 "memory_operand" "=Z")
+- (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f")))
+- (clobber (match_operand:DI 2 "gpc_reg_operand" "=f"))]
++ (fix:SI (match_operand:DF 1 "gpc_reg_operand" "d")))
++ (clobber (match_operand:DI 2 "gpc_reg_operand" "=d"))]
+ "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_DOUBLE_FLOAT
+ && TARGET_PPC_GFXOPT"
+@@ -6113,8 +6113,8 @@
+
+ (define_insn_and_split "fix_truncdfsi2_mfpgpr"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+- (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f")))
+- (clobber (match_operand:DI 2 "gpc_reg_operand" "=f"))
++ (fix:SI (match_operand:DF 1 "gpc_reg_operand" "d")))
++ (clobber (match_operand:DI 2 "gpc_reg_operand" "=d"))
+ (clobber (match_operand:DI 3 "gpc_reg_operand" "=r"))]
+ "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_DOUBLE_FLOAT"
+@@ -6131,8 +6131,8 @@
+ ; because the first makes it clear that operand 0 is not live
+ ; before the instruction.
+ (define_insn "fctiwz"
+- [(set (match_operand:DI 0 "gpc_reg_operand" "=f")
+- (unspec:DI [(fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))]
++ [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
++ (unspec:DI [(fix:SI (match_operand:DF 1 "gpc_reg_operand" "d"))]
+ UNSPEC_FCTIWZ))]
+ "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_DOUBLE_FLOAT"
+@@ -6140,8 +6140,8 @@
+ [(set_attr "type" "fp")])
+
+ (define_insn "btruncdf2"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIZ))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "friz %0,%1"
+ [(set_attr "type" "fp")])
+@@ -6154,8 +6154,8 @@
+ [(set_attr "type" "fp")])
+
+ (define_insn "ceildf2"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIP))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIP))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "frip %0,%1"
+ [(set_attr "type" "fp")])
+@@ -6168,8 +6168,8 @@
+ [(set_attr "type" "fp")])
+
+ (define_insn "floordf2"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIM))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIM))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "frim %0,%1"
+ [(set_attr "type" "fp")])
+@@ -6182,8 +6182,8 @@
+ [(set_attr "type" "fp")])
+
+ (define_insn "rounddf2"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIN))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIN))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "frin %0,%1"
+ [(set_attr "type" "fp")])
+@@ -6198,7 +6198,7 @@
+ ; An UNSPEC is used so we don't have to support SImode in FP registers.
+ (define_insn "stfiwx"
+ [(set (match_operand:SI 0 "memory_operand" "=Z")
+- (unspec:SI [(match_operand:DI 1 "gpc_reg_operand" "f")]
++ (unspec:SI [(match_operand:DI 1 "gpc_reg_operand" "d")]
+ UNSPEC_STFIWX))]
+ "TARGET_PPC_GFXOPT"
+ "stfiwx %1,%y0"
+@@ -6211,15 +6211,15 @@
+ "")
+
+ (define_insn "floatdidf2"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (float:DF (match_operand:DI 1 "gpc_reg_operand" "!f#r")))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (float:DF (match_operand:DI 1 "gpc_reg_operand" "!d#r")))]
+ "(TARGET_POWERPC64 || TARGET_XILINX_FPU) && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
+ "fcfid %0,%1"
+ [(set_attr "type" "fp")])
+
+ (define_insn "fix_truncdfdi2"
+- [(set (match_operand:DI 0 "gpc_reg_operand" "=!f#r")
+- (fix:DI (match_operand:DF 1 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DI 0 "gpc_reg_operand" "=!d#r")
++ (fix:DI (match_operand:DF 1 "gpc_reg_operand" "d")))]
+ "(TARGET_POWERPC64 || TARGET_XILINX_FPU) && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
+ "fctidz %0,%1"
+ [(set_attr "type" "fp")])
+@@ -6247,8 +6247,8 @@
+ ;; from double rounding.
+ (define_insn_and_split "floatdisf2_internal1"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+- (float:SF (match_operand:DI 1 "gpc_reg_operand" "!f#r")))
+- (clobber (match_scratch:DF 2 "=f"))]
++ (float:SF (match_operand:DI 1 "gpc_reg_operand" "!d#r")))
++ (clobber (match_scratch:DF 2 "=d"))]
+ "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
+ "#"
+ "&& reload_completed"
+@@ -8497,8 +8497,8 @@
+ ;; The "??" is a kludge until we can figure out a more reasonable way
+ ;; of handling these non-offsettable values.
+ (define_insn "*movdf_hardfloat32"
+- [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,m,f,f,m,!r,!r,!r")
+- (match_operand:DF 1 "input_operand" "r,m,r,f,m,f,G,H,F"))]
++ [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,m,d,d,m,!r,!r,!r")
++ (match_operand:DF 1 "input_operand" "r,m,r,d,m,d,G,H,F"))]
+ "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && (gpc_reg_operand (operands[0], DFmode)
+ || gpc_reg_operand (operands[1], DFmode))"
+@@ -8637,8 +8637,8 @@
+ ; ld/std require word-aligned displacements -> 'Y' constraint.
+ ; List Y->r and r->Y before r->r for reload.
+ (define_insn "*movdf_hardfloat64_mfpgpr"
+- [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,*c*l,!r,*h,!r,!r,!r,r,f")
+- (match_operand:DF 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F,f,r"))]
++ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,d,d,m,*c*l,!r,*h,!r,!r,!r,r,d")
++ (match_operand:DF 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F,d,r"))]
+ "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_DOUBLE_FLOAT
+ && (gpc_reg_operand (operands[0], DFmode)
+@@ -8664,8 +8664,8 @@
+ ; ld/std require word-aligned displacements -> 'Y' constraint.
+ ; List Y->r and r->Y before r->r for reload.
+ (define_insn "*movdf_hardfloat64"
+- [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,*c*l,!r,*h,!r,!r,!r")
+- (match_operand:DF 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F"))]
++ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,d,d,m,*c*l,!r,*h,!r,!r,!r")
++ (match_operand:DF 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F"))]
+ "TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_DOUBLE_FLOAT
+ && (gpc_reg_operand (operands[0], DFmode)
+@@ -8715,8 +8715,8 @@
+ ; otherwise reload, given m->f, will try to pick f->f and reload it,
+ ; which doesn't make progress. Likewise r->Y must be before r->r.
+ (define_insn_and_split "*movtf_internal"
+- [(set (match_operand:TF 0 "nonimmediate_operand" "=o,f,f,r,Y,r")
+- (match_operand:TF 1 "input_operand" "f,o,f,YGHF,r,r"))]
++ [(set (match_operand:TF 0 "nonimmediate_operand" "=o,d,d,r,Y,r")
++ (match_operand:TF 1 "input_operand" "d,o,d,YGHF,r,r"))]
+ "!TARGET_IEEEQUAD
+ && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128
+ && (gpc_reg_operand (operands[0], TFmode)
+@@ -8770,9 +8770,9 @@
+ })
+
+ (define_insn_and_split "*extenddftf2_internal"
+- [(set (match_operand:TF 0 "nonimmediate_operand" "=o,f,&f,r")
+- (float_extend:TF (match_operand:DF 1 "input_operand" "fr,mf,mf,rmGHF")))
+- (use (match_operand:DF 2 "zero_reg_mem_operand" "rf,m,f,n"))]
++ [(set (match_operand:TF 0 "nonimmediate_operand" "=o,d,&d,r")
++ (float_extend:TF (match_operand:DF 1 "input_operand" "dr,md,md,rmGHF")))
++ (use (match_operand:DF 2 "zero_reg_mem_operand" "rd,m,d,n"))]
+ "!TARGET_IEEEQUAD
+ && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && TARGET_LONG_DOUBLE_128"
+@@ -8813,8 +8813,8 @@
+ "")
+
+ (define_insn_and_split "trunctfdf2_internal1"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f,?f")
+- (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "0,f")))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d")
++ (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "0,d")))]
+ "!TARGET_IEEEQUAD && !TARGET_XL_COMPAT
+ && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+ "@
+@@ -8829,8 +8829,8 @@
+ [(set_attr "type" "fp")])
+
+ (define_insn "trunctfdf2_internal2"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "f")))]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "d")))]
+ "!TARGET_IEEEQUAD && TARGET_XL_COMPAT
+ && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && TARGET_LONG_DOUBLE_128"
+@@ -8855,8 +8855,8 @@
+
+ (define_insn_and_split "trunctfsf2_fprs"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+- (float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "f")))
+- (clobber (match_scratch:DF 2 "=f"))]
++ (float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "d")))
++ (clobber (match_scratch:DF 2 "=d"))]
+ "!TARGET_IEEEQUAD
+ && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
+ && TARGET_LONG_DOUBLE_128"
+@@ -8885,10 +8885,10 @@
+ ; fadd, but rounding towards zero.
+ ; This is probably not the optimal code sequence.
+ (define_insn "fix_trunc_helper"
+- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+- (unspec:DF [(match_operand:TF 1 "gpc_reg_operand" "f")]
++ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
++ (unspec:DF [(match_operand:TF 1 "gpc_reg_operand" "d")]
+ UNSPEC_FIX_TRUNC_TF))
+- (clobber (match_operand:DF 2 "gpc_reg_operand" "=&f"))]
++ (clobber (match_operand:DF 2 "gpc_reg_operand" "=&d"))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "mffs %2\n\tmtfsb1 31\n\tmtfsb0 30\n\tfadd %0,%1,%L1\n\tmtfsf 1,%2"
+ [(set_attr "type" "fp")
+@@ -8929,10 +8929,10 @@
+
+ (define_insn_and_split "*fix_trunctfsi2_internal"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+- (fix:SI (match_operand:TF 1 "gpc_reg_operand" "f")))
+- (clobber (match_operand:DF 2 "gpc_reg_operand" "=f"))
+- (clobber (match_operand:DF 3 "gpc_reg_operand" "=&f"))
+- (clobber (match_operand:DI 4 "gpc_reg_operand" "=f"))
++ (fix:SI (match_operand:TF 1 "gpc_reg_operand" "d")))
++ (clobber (match_operand:DF 2 "gpc_reg_operand" "=d"))
++ (clobber (match_operand:DF 3 "gpc_reg_operand" "=&d"))
++ (clobber (match_operand:DI 4 "gpc_reg_operand" "=d"))
+ (clobber (match_operand:DI 5 "offsettable_mem_operand" "=o"))]
+ "!TARGET_IEEEQUAD
+ && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+@@ -8962,8 +8962,8 @@
+ "")
+
+ (define_insn "negtf2_internal"
+- [(set (match_operand:TF 0 "gpc_reg_operand" "=f")
+- (neg:TF (match_operand:TF 1 "gpc_reg_operand" "f")))]
++ [(set (match_operand:TF 0 "gpc_reg_operand" "=d")
++ (neg:TF (match_operand:TF 1 "gpc_reg_operand" "d")))]
+ "!TARGET_IEEEQUAD
+ && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+ "*
+@@ -9028,8 +9028,8 @@
+ ; List r->r after r->"o<>", otherwise reload will try to reload a
+ ; non-offsettable address by using r->r which won't make progress.
+ (define_insn "*movdi_internal32"
+- [(set (match_operand:DI 0 "rs6000_nonimmediate_operand" "=o<>,r,r,*f,*f,m,r")
+- (match_operand:DI 1 "input_operand" "r,r,m,f,m,f,IJKnGHF"))]
++ [(set (match_operand:DI 0 "rs6000_nonimmediate_operand" "=o<>,r,r,*d,*d,m,r")
++ (match_operand:DI 1 "input_operand" "r,r,m,d,m,d,IJKnGHF"))]
+ "! TARGET_POWERPC64
+ && (gpc_reg_operand (operands[0], DImode)
+ || gpc_reg_operand (operands[1], DImode))"
+@@ -9073,8 +9073,8 @@
+ { rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
+
+ (define_insn "*movdi_mfpgpr"
+- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*f,*f,m,r,*h,*h,r,*f")
+- (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,f,m,f,*h,r,0,*f,r"))]
++ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*d,*d,m,r,*h,*h,r,*d")
++ (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,d,m,d,*h,r,0,*d,r"))]
+ "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
+ && (gpc_reg_operand (operands[0], DImode)
+ || gpc_reg_operand (operands[1], DImode))"
+@@ -9098,8 +9098,8 @@
+ (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4,4")])
+
+ (define_insn "*movdi_internal64"
+- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*f,*f,m,r,*h,*h")
+- (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,f,m,f,*h,r,0"))]
++ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*d,*d,m,r,*h,*h")
++ (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,d,m,d,*h,r,0"))]
+ "TARGET_POWERPC64 && (!TARGET_MFPGPR || !TARGET_HARD_FLOAT || !TARGET_FPRS)
+ && (gpc_reg_operand (operands[0], DImode)
+ || gpc_reg_operand (operands[1], DImode))"
+@@ -10293,7 +10293,7 @@
+ [(set_attr "type" "store_ux,store_u")])
+
+ (define_insn "*movdf_update1"
+- [(set (match_operand:DF 3 "gpc_reg_operand" "=f,f")
++ [(set (match_operand:DF 3 "gpc_reg_operand" "=d,d")
+ (mem:DF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
+ (match_operand:SI 2 "reg_or_short_operand" "r,I"))))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
+@@ -10309,7 +10309,7 @@
+ (define_insn "*movdf_update2"
+ [(set (mem:DF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
+ (match_operand:SI 2 "reg_or_short_operand" "r,I")))
+- (match_operand:DF 3 "gpc_reg_operand" "f,f"))
++ (match_operand:DF 3 "gpc_reg_operand" "d,d"))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_UPDATE
+@@ -12237,8 +12237,8 @@
+
+ (define_insn "*cmpdf_internal1"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+- (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "f")
+- (match_operand:DF 2 "gpc_reg_operand" "f")))]
++ (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "d")
++ (match_operand:DF 2 "gpc_reg_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "fcmpu %0,%1,%2"
+ [(set_attr "type" "fpcompare")])
+@@ -12246,8 +12246,8 @@
+ ;; Only need to compare second words if first words equal
+ (define_insn "*cmptf_internal1"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+- (compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "f")
+- (match_operand:TF 2 "gpc_reg_operand" "f")))]
++ (compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "d")
++ (match_operand:TF 2 "gpc_reg_operand" "d")))]
+ "!TARGET_IEEEQUAD && !TARGET_XL_COMPAT
+ && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128"
+ "fcmpu %0,%1,%2\;bne %0,$+8\;fcmpu %0,%L1,%L2"
+@@ -12256,16 +12256,16 @@
+
+ (define_insn_and_split "*cmptf_internal2"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+- (compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "f")
+- (match_operand:TF 2 "gpc_reg_operand" "f")))
+- (clobber (match_scratch:DF 3 "=f"))
+- (clobber (match_scratch:DF 4 "=f"))
+- (clobber (match_scratch:DF 5 "=f"))
+- (clobber (match_scratch:DF 6 "=f"))
+- (clobber (match_scratch:DF 7 "=f"))
+- (clobber (match_scratch:DF 8 "=f"))
+- (clobber (match_scratch:DF 9 "=f"))
+- (clobber (match_scratch:DF 10 "=f"))]
++ (compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "d")
++ (match_operand:TF 2 "gpc_reg_operand" "d")))
++ (clobber (match_scratch:DF 3 "=d"))
++ (clobber (match_scratch:DF 4 "=d"))
++ (clobber (match_scratch:DF 5 "=d"))
++ (clobber (match_scratch:DF 6 "=d"))
++ (clobber (match_scratch:DF 7 "=d"))
++ (clobber (match_scratch:DF 8 "=d"))
++ (clobber (match_scratch:DF 9 "=d"))
++ (clobber (match_scratch:DF 10 "=d"))]
+ "!TARGET_IEEEQUAD && TARGET_XL_COMPAT
+ && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128"
+ "#"
+@@ -14741,7 +14741,7 @@
+ (use (match_operand:P 1 "symbol_ref_operand" "s"))
+ (use (match_operand:P 2 "gpc_reg_operand" "r"))
+ (set (match_operand:DF 3 "memory_operand" "=m")
+- (match_operand:DF 4 "gpc_reg_operand" "f"))])]
++ (match_operand:DF 4 "gpc_reg_operand" "d"))])]
+ ""
+ "bl %z1"
+ [(set_attr "type" "branch")
+@@ -14861,7 +14861,7 @@
+ (clobber (match_operand:P 1 "register_operand" "=l"))
+ (use (match_operand:P 2 "symbol_ref_operand" "s"))
+ (use (match_operand:P 3 "gpc_reg_operand" "r"))
+- (set (match_operand:DF 4 "gpc_reg_operand" "=f")
++ (set (match_operand:DF 4 "gpc_reg_operand" "=d")
+ (match_operand:DF 5 "memory_operand" "m"))])]
+ ""
+ "b %z2"
+Index: gcc-4.4.1/gcc/config/rs6000/ppu_intrinsics.h
+===================================================================
+--- gcc-4.4.1.orig/gcc/config/rs6000/ppu_intrinsics.h 2009-10-06 14:08:35.837316319 -0700
++++ gcc-4.4.1/gcc/config/rs6000/ppu_intrinsics.h 2009-10-06 14:09:12.087313658 -0700
+@@ -385,11 +385,11 @@ typedef int __V4SI __attribute__((vector
+
+ #define __mffs() __extension__ \
+ ({double result; \
+- __asm__ volatile ("mffs %0" : "=f" (result)); \
++ __asm__ volatile ("mffs %0" : "=d" (result)); \
+ result; })
+
+ #define __mtfsf(mask,value) \
+- __asm__ volatile ("mtfsf %0,%1" : : "n" (mask), "f" ((double) (value)))
++ __asm__ volatile ("mtfsf %0,%1" : : "n" (mask), "d" ((double) (value)))
+
+ #define __mtfsfi(bits,field) \
+ __asm__ volatile ("mtfsfi %0,%1" : : "n" (bits), "n" (field))
+@@ -400,8 +400,8 @@ typedef int __V4SI __attribute__((vector
+ #define __setflm(v) __extension__ \
+ ({double result; \
+ __asm__ volatile ("mffs %0\n\tmtfsf 255,%1" \
+- : "=&f" (result) \
+- : "f" ((double) (v))); \
++ : "=&d" (result) \
++ : "d" ((double) (v))); \
+ result; })
+
+ /* __builtin_fabs may perform unnecessary rounding. */
+@@ -416,7 +416,7 @@ static __inline__ double
+ __fabs(double x)
+ {
+ double r;
+- __asm__("fabs %0,%1" : "=f"(r) : "f"(x));
++ __asm__("fabs %0,%1" : "=d"(r) : "d"(x));
+ return r;
+ }
+
+@@ -434,7 +434,7 @@ static __inline__ double
+ __fnabs(double x)
+ {
+ double r;
+- __asm__("fnabs %0,%1" : "=f"(r) : "f"(x));
++ __asm__("fnabs %0,%1" : "=d"(r) : "d"(x));
+ return r;
+ }
+
+@@ -453,7 +453,7 @@ static __inline__ double
+ __fmadd(double x, double y, double z)
+ {
+ double r;
+- __asm__("fmadd %0,%1,%2,%3" : "=f"(r) : "f"(x),"f"(y),"f"(z));
++ __asm__("fmadd %0,%1,%2,%3" : "=d"(r) : "d"(x),"d"(y),"d"(z));
+ return r;
+ }
+
+@@ -463,7 +463,7 @@ static __inline__ double
+ __fmsub(double x, double y, double z)
+ {
+ double r;
+- __asm__("fmsub %0,%1,%2,%3" : "=f"(r) : "f"(x),"f"(y),"f"(z));
++ __asm__("fmsub %0,%1,%2,%3" : "=d"(r) : "d"(x),"d"(y),"d"(z));
+ return r;
+ }
+
+@@ -473,7 +473,7 @@ static __inline__ double
+ __fnmadd(double x, double y, double z)
+ {
+ double r;
+- __asm__("fnmadd %0,%1,%2,%3" : "=f"(r) : "f"(x),"f"(y),"f"(z));
++ __asm__("fnmadd %0,%1,%2,%3" : "=d"(r) : "d"(x),"d"(y),"d"(z));
+ return r;
+ }
+
+@@ -483,7 +483,7 @@ static __inline__ double
+ __fnmsub(double x, double y, double z)
+ {
+ double r;
+- __asm__("fnmsub %0,%1,%2,%3" : "=f"(r) : "f"(x),"f"(y),"f"(z));
++ __asm__("fnmsub %0,%1,%2,%3" : "=d"(r) : "d"(x),"d"(y),"d"(z));
+ return r;
+ }
+
+@@ -533,7 +533,7 @@ static __inline__ double
+ __fsel(double x, double y, double z)
+ {
+ double r;
+- __asm__("fsel %0,%1,%2,%3" : "=f"(r) : "f"(x),"f"(y),"f"(z));
++ __asm__("fsel %0,%1,%2,%3" : "=d"(r) : "d"(x),"d"(y),"d"(z));
+ return r;
+ }
+
+@@ -552,7 +552,7 @@ static __inline__ double
+ __frsqrte(double x)
+ {
+ double r;
+- __asm__("frsqrte %0,%1" : "=f" (r) : "f" (x));
++ __asm__("frsqrte %0,%1" : "=d" (r) : "d" (x));
+ return r;
+ }
+
+@@ -570,7 +570,7 @@ static __inline__ double
+ __fsqrt(double x)
+ {
+ double r;
+- __asm__("fsqrt %0,%1" : "=f"(r) : "f"(x));
++ __asm__("fsqrt %0,%1" : "=d"(r) : "d"(x));
+ return r;
+ }
+
+@@ -588,7 +588,7 @@ static __inline__ double
+ __fmul(double a, double b)
+ {
+ double d;
+- __asm__ ("fmul %0,%1,%2" : "=f" (d) : "f" (a), "f" (b));
++ __asm__ ("fmul %0,%1,%2" : "=d" (d) : "d" (a), "d" (b));
+ return d;
+ }
+
+@@ -597,7 +597,7 @@ static __inline__ float
+ __fmuls (float a, float b)
+ {
+ float d;
+- __asm__ ("fmuls %0,%1,%2" : "=f" (d) : "f" (a), "f" (b));
++ __asm__ ("fmuls %0,%1,%2" : "=d" (d) : "f" (a), "f" (b));
+ return d;
+ }
+
+@@ -606,7 +606,7 @@ static __inline__ float
+ __frsp (float a)
+ {
+ float d;
+- __asm__ ("frsp %0,%1" : "=f" (d) : "f" (a));
++ __asm__ ("frsp %0,%1" : "=d" (d) : "f" (a));
+ return d;
+ }
+
+@@ -615,7 +615,7 @@ static __inline__ double
+ __fcfid (long long a)
+ {
+ double d;
+- __asm__ ("fcfid %0,%1" : "=f" (d) : "f" (a));
++ __asm__ ("fcfid %0,%1" : "=d" (d) : "d" (a));
+ return d;
+ }
+
+@@ -624,7 +624,7 @@ static __inline__ long long
+ __fctid (double a)
+ {
+ long long d;
+- __asm__ ("fctid %0,%1" : "=f" (d) : "f" (a));
++ __asm__ ("fctid %0,%1" : "=d" (d) : "d" (a));
+ return d;
+ }
+
+@@ -633,7 +633,7 @@ static __inline__ long long
+ __fctidz (double a)
+ {
+ long long d;
+- __asm__ ("fctidz %0,%1" : "=f" (d) : "f" (a));
++ __asm__ ("fctidz %0,%1" : "=d" (d) : "d" (a));
+ return d;
+ }
+
+@@ -642,7 +642,7 @@ static __inline__ int
+ __fctiw (double a)
+ {
+ unsigned long long d;
+- __asm__ ("fctiw %0,%1" : "=f" (d) : "f" (a));
++ __asm__ ("fctiw %0,%1" : "=d" (d) : "d" (a));
+ return (int) d;
+ }
+
+@@ -651,7 +651,7 @@ static __inline__ int
+ __fctiwz (double a)
+ {
+ long long d;
+- __asm__ ("fctiwz %0,%1" : "=f" (d) : "f" (a));
++ __asm__ ("fctiwz %0,%1" : "=d" (d) : "d" (a));
+ return (int) d;
+ }
+
diff --git a/recipes/gcc/gcc-4.4.1/gcc-ppc_single_precision_regs.patch b/recipes/gcc/gcc-4.4.1/gcc-ppc_single_precision_regs.patch
new file mode 100644
index 0000000000..5b35d6e74c
--- /dev/null
+++ b/recipes/gcc/gcc-4.4.1/gcc-ppc_single_precision_regs.patch
@@ -0,0 +1,60 @@
+Index: gcc-4.4.1/gcc/config/rs6000/rs6000.c
+===================================================================
+--- gcc-4.4.1.orig/gcc/config/rs6000/rs6000.c 2009-10-06 13:51:50.427316302 -0700
++++ gcc-4.4.1/gcc/config/rs6000/rs6000.c 2009-10-06 14:09:04.737313663 -0700
+@@ -22580,7 +22580,8 @@ rs6000_function_value (const_tree valtyp
+ if (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
+ /* _Decimal128 must use an even/odd register pair. */
+ regno = (mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN;
+- else if (SCALAR_FLOAT_TYPE_P (valtype) && TARGET_HARD_FLOAT && TARGET_FPRS)
++ else if (SCALAR_FLOAT_TYPE_P (valtype) && TARGET_HARD_FLOAT && TARGET_FPRS
++ && ((TARGET_SINGLE_FLOAT && (mode == SFmode)) || TARGET_DOUBLE_FLOAT))
+ regno = FP_ARG_RETURN;
+ else if (TREE_CODE (valtype) == COMPLEX_TYPE
+ && targetm.calls.split_complex_arg)
+Index: gcc-4.4.1/gcc/config/rs6000/rs6000.md
+===================================================================
+--- gcc-4.4.1.orig/gcc/config/rs6000/rs6000.md 2009-10-06 14:08:35.827340958 -0700
++++ gcc-4.4.1/gcc/config/rs6000/rs6000.md 2009-10-06 14:09:04.737313663 -0700
+@@ -8143,8 +8143,8 @@
+ (define_insn "*movsi_internal1"
+ [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h")
+ (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,R,*h,r,r,r,0"))]
+- "gpc_reg_operand (operands[0], SImode)
+- || gpc_reg_operand (operands[1], SImode)"
++ "!TARGET_SINGLE_FPU &&
++ gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode)"
+ "@
+ mr %0,%1
+ {cal|la} %0,%a1
+@@ -8162,6 +8162,30 @@
+ [(set_attr "type" "*,*,load,store,*,*,*,*,mfjmpr,*,mtjmpr,*,*")
+ (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4")])
+
++(define_insn "*movsi_internal1_single"
++ [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h,m,*f")
++ (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,R,*h,r,r,r,0,f,m"))]
++ "TARGET_SINGLE_FPU &&
++ gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode)"
++ "@
++ mr %0,%1
++ {cal|la} %0,%a1
++ {l%U1%X1|lwz%U1%X1} %0,%1
++ {st%U0%X0|stw%U0%X0} %1,%0
++ {lil|li} %0,%1
++ {liu|lis} %0,%v1
++ #
++ {cal|la} %0,%a1
++ mf%1 %0
++ mt%0 %1
++ mt%0 %1
++ mt%0 %1
++ {cror 0,0,0|nop}
++ stfs%U0%X0 %1, %0
++ lfs%U1%X1 %0, %1"
++ [(set_attr "type" "*,*,load,store,*,*,*,*,mfjmpr,*,mtjmpr,*,*,*,*")
++ (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4,4,4")])
++
+ ;; Split a load of a large constant into the appropriate two-insn
+ ;; sequence.
+
diff --git a/recipes/gcc/gcc-4.4.1/gcc-pr41175.patch b/recipes/gcc/gcc-4.4.1/gcc-pr41175.patch
new file mode 100644
index 0000000000..10da543958
--- /dev/null
+++ b/recipes/gcc/gcc-4.4.1/gcc-pr41175.patch
@@ -0,0 +1,1172 @@
+Index: gcc-4.4.1/gcc/testsuite/gcc.target/powerpc/pr41175.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ gcc-4.4.1/gcc/testsuite/gcc.target/powerpc/pr41175.c 2009-10-06 14:09:19.757404626 -0700
+@@ -0,0 +1,461 @@
++/* PR target/41175 */
++/* { dg-do run } */
++/* { dg-options "-Os" } */
++
++#define X2(n) X1(n##0) X1(n##1)
++#define X4(n) X2(n##0) X2(n##1)
++#define X8(n) X4(n##0) X4(n##1)
++
++#ifndef __SPE__
++#define FLOAT_REG_CONSTRAINT "f"
++#else
++#define FLOAT_REG_CONSTRAINT "r"
++#endif
++
++volatile int ll;
++
++__attribute__((noinline)) void
++foo (void)
++{
++ asm volatile ("" : : : "memory");
++}
++
++__attribute__((noinline)) void
++bar (char *p)
++{
++ asm volatile ("" : : "r" (p) : "memory");
++}
++
++__attribute__((noinline)) void
++f1 (void)
++{
++ int mem;
++#undef X1
++#define X1(n) int gpr##n = 0;
++ X8(a) X8(b) X8(c)
++#undef X1
++#define X1(n) "+r" (gpr##n),
++ asm volatile ("" : X8(a) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(b) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(c) "=m" (mem) : : "memory");
++ foo ();
++#undef X1
++#define X1(n) "r" (gpr##n),
++ asm volatile ("" : : X8(a) "m" (mem) : "memory");
++ asm volatile ("" : : X8(b) "m" (mem) : "memory");
++ asm volatile ("" : : X8(c) "m" (mem) : "memory");
++}
++
++__attribute__((noinline)) void
++f2 (void)
++{
++ int mem;
++#undef X1
++#define X1(n) int gpr##n = 0;
++ X8(a) X8(b) X8(c)
++#undef X1
++#define X1(n) "+r" (gpr##n),
++ asm volatile ("" : X8(a) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(b) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(c) "=m" (mem) : : "memory");
++ char *pp = __builtin_alloca (ll);
++ bar (pp);
++#undef X1
++#define X1(n) "r" (gpr##n),
++ asm volatile ("" : : X8(a) "m" (mem) : "memory");
++ asm volatile ("" : : X8(b) "m" (mem) : "memory");
++ asm volatile ("" : : X8(c) "m" (mem) : "memory");
++}
++
++__attribute__((noinline)) void
++f3 (void)
++{
++ int mem;
++#undef X1
++#define X1(n) int gpr##n = 0;
++ X8(a) X8(b) X8(c)
++#undef X1
++#define X1(n) "+r" (gpr##n),
++ asm volatile ("" : X8(a) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(b) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(c) "=m" (mem) : : "memory");
++#undef X1
++#define X1(n) "r" (gpr##n),
++ asm volatile ("" : : X8(a) "m" (mem) : "memory");
++ asm volatile ("" : : X8(b) "m" (mem) : "memory");
++ asm volatile ("" : : X8(c) "m" (mem) : "memory");
++}
++
++#ifndef __NO_FPRS__
++__attribute__((noinline)) void
++f4 (void)
++{
++ int mem;
++#undef X1
++#define X1(n) int gpr##n = 0;
++ X8(a) X8(b) X8(c)
++#undef X1
++#define X1(n) double fpr##n = 0.0;
++ X4(d)
++#undef X1
++#define X1(n) "+r" (gpr##n),
++ asm volatile ("" : X8(a) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(b) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(c) "=m" (mem) : : "memory");
++#undef X1
++#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : X4(d) "=m" (mem) : : "memory");
++ foo ();
++#undef X1
++#define X1(n) "r" (gpr##n),
++ asm volatile ("" : : X8(a) "m" (mem) : "memory");
++ asm volatile ("" : : X8(b) "m" (mem) : "memory");
++ asm volatile ("" : : X8(c) "m" (mem) : "memory");
++#undef X1
++#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : : X4(d) "m" (mem) : "memory");
++}
++
++__attribute__((noinline)) void
++f5 (void)
++{
++ int mem;
++#undef X1
++#define X1(n) int gpr##n = 0;
++ X8(a) X8(b) X8(c)
++#undef X1
++#define X1(n) double fpr##n = 0.0;
++ X4(d)
++#undef X1
++#define X1(n) "+r" (gpr##n),
++ asm volatile ("" : X8(a) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(b) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(c) "=m" (mem) : : "memory");
++#undef X1
++#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : X4(d) "=m" (mem) : : "memory");
++ char *pp = __builtin_alloca (ll);
++ bar (pp);
++#undef X1
++#define X1(n) "r" (gpr##n),
++ asm volatile ("" : : X8(a) "m" (mem) : "memory");
++ asm volatile ("" : : X8(b) "m" (mem) : "memory");
++ asm volatile ("" : : X8(c) "m" (mem) : "memory");
++#undef X1
++#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : : X4(d) "m" (mem) : "memory");
++}
++
++__attribute__((noinline)) void
++f6 (void)
++{
++ int mem;
++#undef X1
++#define X1(n) int gpr##n = 0;
++ X8(a) X8(b) X8(c)
++#undef X1
++#define X1(n) double fpr##n = 0.0;
++ X4(d)
++#undef X1
++#define X1(n) "+r" (gpr##n),
++ asm volatile ("" : X8(a) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(b) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(c) "=m" (mem) : : "memory");
++#undef X1
++#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : X4(d) "=m" (mem) : : "memory");
++#undef X1
++#define X1(n) "r" (gpr##n),
++ asm volatile ("" : : X8(a) "m" (mem) : "memory");
++ asm volatile ("" : : X8(b) "m" (mem) : "memory");
++ asm volatile ("" : : X8(c) "m" (mem) : "memory");
++#undef X1
++#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : : X4(d) "m" (mem) : "memory");
++}
++
++__attribute__((noinline)) void
++f7 (void)
++{
++ int mem;
++#undef X1
++#define X1(n) int gpr##n = 0;
++ X8(a) X8(b) X8(c)
++#undef X1
++#define X1(n) double fpr##n = 0.0;
++ X2(d)
++#undef X1
++#define X1(n) "+r" (gpr##n),
++ asm volatile ("" : X8(a) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(b) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(c) "=m" (mem) : : "memory");
++#undef X1
++#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : X2(d) "=m" (mem) : : "memory");
++ foo ();
++#undef X1
++#define X1(n) "r" (gpr##n),
++ asm volatile ("" : : X8(a) "m" (mem) : "memory");
++ asm volatile ("" : : X8(b) "m" (mem) : "memory");
++ asm volatile ("" : : X8(c) "m" (mem) : "memory");
++#undef X1
++#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : : X2(d) "m" (mem) : "memory");
++}
++
++__attribute__((noinline)) void
++f8 (void)
++{
++ int mem;
++#undef X1
++#define X1(n) int gpr##n = 0;
++ X8(a) X8(b) X8(c)
++#undef X1
++#define X1(n) double fpr##n = 0.0;
++ X2(d)
++#undef X1
++#define X1(n) "+r" (gpr##n),
++ asm volatile ("" : X8(a) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(b) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(c) "=m" (mem) : : "memory");
++#undef X1
++#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : X2(d) "=m" (mem) : : "memory");
++ char *pp = __builtin_alloca (ll);
++ bar (pp);
++#undef X1
++#define X1(n) "r" (gpr##n),
++ asm volatile ("" : : X8(a) "m" (mem) : "memory");
++ asm volatile ("" : : X8(b) "m" (mem) : "memory");
++ asm volatile ("" : : X8(c) "m" (mem) : "memory");
++#undef X1
++#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : : X2(d) "m" (mem) : "memory");
++}
++
++__attribute__((noinline)) void
++f9 (void)
++{
++ int mem;
++#undef X1
++#define X1(n) int gpr##n = 0;
++ X8(a) X8(b) X8(c)
++#undef X1
++#define X1(n) double fpr##n = 0.0;
++ X2(d)
++#undef X1
++#define X1(n) "+r" (gpr##n),
++ asm volatile ("" : X8(a) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(b) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(c) "=m" (mem) : : "memory");
++#undef X1
++#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : X2(d) "=m" (mem) : : "memory");
++#undef X1
++#define X1(n) "r" (gpr##n),
++ asm volatile ("" : : X8(a) "m" (mem) : "memory");
++ asm volatile ("" : : X8(b) "m" (mem) : "memory");
++ asm volatile ("" : : X8(c) "m" (mem) : "memory");
++#undef X1
++#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : : X2(d) "m" (mem) : "memory");
++}
++
++__attribute__((noinline)) void
++f10 (void)
++{
++ int mem;
++#undef X1
++#define X1(n) int gpr##n = 0;
++ X8(a) X8(b) X4(c)
++#undef X1
++#define X1(n) double fpr##n = 0.0;
++ X1(d)
++#undef X1
++#define X1(n) "+r" (gpr##n),
++ asm volatile ("" : X8(a) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(b) "=m" (mem) : : "memory");
++ asm volatile ("" : X4(c) "=m" (mem) : : "memory");
++#undef X1
++#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : X1(d) "=m" (mem) : : "memory");
++ foo ();
++#undef X1
++#define X1(n) "r" (gpr##n),
++ asm volatile ("" : : X8(a) "m" (mem) : "memory");
++ asm volatile ("" : : X8(b) "m" (mem) : "memory");
++ asm volatile ("" : : X4(c) "m" (mem) : "memory");
++#undef X1
++#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : : X1(d) "m" (mem) : "memory");
++}
++
++__attribute__((noinline)) void
++f11 (void)
++{
++ int mem;
++#undef X1
++#define X1(n) int gpr##n = 0;
++ X8(a) X8(b) X4(c)
++#undef X1
++#define X1(n) double fpr##n = 0.0;
++ X1(d)
++#undef X1
++#define X1(n) "+r" (gpr##n),
++ asm volatile ("" : X8(a) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(b) "=m" (mem) : : "memory");
++ asm volatile ("" : X4(c) "=m" (mem) : : "memory");
++#undef X1
++#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : X1(d) "=m" (mem) : : "memory");
++ char *pp = __builtin_alloca (ll);
++ bar (pp);
++#undef X1
++#define X1(n) "r" (gpr##n),
++ asm volatile ("" : : X8(a) "m" (mem) : "memory");
++ asm volatile ("" : : X8(b) "m" (mem) : "memory");
++ asm volatile ("" : : X4(c) "m" (mem) : "memory");
++#undef X1
++#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : : X1(d) "m" (mem) : "memory");
++}
++
++__attribute__((noinline)) void
++f12 (void)
++{
++ int mem;
++#undef X1
++#define X1(n) int gpr##n = 0;
++ X8(a) X8(b) X4(c)
++#undef X1
++#define X1(n) double fpr##n = 0.0;
++ X1(d)
++#undef X1
++#define X1(n) "+r" (gpr##n),
++ asm volatile ("" : X8(a) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(b) "=m" (mem) : : "memory");
++ asm volatile ("" : X4(c) "=m" (mem) : : "memory");
++#undef X1
++#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : X1(d) "=m" (mem) : : "memory");
++#undef X1
++#define X1(n) "r" (gpr##n),
++ asm volatile ("" : : X8(a) "m" (mem) : "memory");
++ asm volatile ("" : : X8(b) "m" (mem) : "memory");
++ asm volatile ("" : : X4(c) "m" (mem) : "memory");
++#undef X1
++#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : : X1(d) "m" (mem) : "memory");
++}
++
++__attribute__((noinline)) void
++f13 (void)
++{
++ int mem;
++#undef X1
++#define X1(n) int gpr##n = 0;
++ X8(a) X8(b) X2(c)
++#undef X1
++#define X1(n) double fpr##n = 0.0;
++ X8(d)
++#undef X1
++#define X1(n) "+r" (gpr##n),
++ asm volatile ("" : X8(a) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(b) "=m" (mem) : : "memory");
++ asm volatile ("" : X2(c) "=m" (mem) : : "memory");
++#undef X1
++#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : X8(d) "=m" (mem) : : "memory");
++ foo ();
++#undef X1
++#define X1(n) "r" (gpr##n),
++ asm volatile ("" : : X8(a) "m" (mem) : "memory");
++ asm volatile ("" : : X8(b) "m" (mem) : "memory");
++ asm volatile ("" : : X2(c) "m" (mem) : "memory");
++#undef X1
++#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : : X8(d) "m" (mem) : "memory");
++}
++
++__attribute__((noinline)) void
++f14 (void)
++{
++ int mem;
++#undef X1
++#define X1(n) int gpr##n = 0;
++ X8(a) X8(b) X2(c)
++#undef X1
++#define X1(n) double fpr##n = 0.0;
++ X8(d)
++#undef X1
++#define X1(n) "+r" (gpr##n),
++ asm volatile ("" : X8(a) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(b) "=m" (mem) : : "memory");
++ asm volatile ("" : X2(c) "=m" (mem) : : "memory");
++#undef X1
++#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : X8(d) "=m" (mem) : : "memory");
++ char *pp = __builtin_alloca (ll);
++ bar (pp);
++#undef X1
++#define X1(n) "r" (gpr##n),
++ asm volatile ("" : : X8(a) "m" (mem) : "memory");
++ asm volatile ("" : : X8(b) "m" (mem) : "memory");
++ asm volatile ("" : : X2(c) "m" (mem) : "memory");
++#undef X1
++#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : : X8(d) "m" (mem) : "memory");
++}
++
++__attribute__((noinline)) void
++f15 (void)
++{
++ int mem;
++#undef X1
++#define X1(n) int gpr##n = 0;
++ X8(a) X8(b) X2(c)
++#undef X1
++#define X1(n) double fpr##n = 0.0;
++ X8(d)
++#undef X1
++#define X1(n) "+r" (gpr##n),
++ asm volatile ("" : X8(a) "=m" (mem) : : "memory");
++ asm volatile ("" : X8(b) "=m" (mem) : : "memory");
++ asm volatile ("" : X2(c) "=m" (mem) : : "memory");
++#undef X1
++#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : X8(d) "=m" (mem) : : "memory");
++#undef X1
++#define X1(n) "r" (gpr##n),
++ asm volatile ("" : : X8(a) "m" (mem) : "memory");
++ asm volatile ("" : : X8(b) "m" (mem) : "memory");
++ asm volatile ("" : : X2(c) "m" (mem) : "memory");
++#undef X1
++#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n),
++ asm volatile ("" : : X8(d) "m" (mem) : "memory");
++}
++#endif
++
++int
++main ()
++{
++ ll = 60;
++ f1 ();
++ f2 ();
++ f3 ();
++#ifndef __NO_FPRS__
++ f4 ();
++ f5 ();
++ f6 ();
++ f7 ();
++ f8 ();
++ f9 ();
++ f10 ();
++ f11 ();
++ f12 ();
++ f13 ();
++ f14 ();
++ f15 ();
++#endif
++ return 0;
++}
+Index: gcc-4.4.1/gcc/config/rs6000/spe.md
+===================================================================
+--- gcc-4.4.1.orig/gcc/config/rs6000/spe.md 2009-10-06 13:51:50.387320717 -0700
++++ gcc-4.4.1/gcc/config/rs6000/spe.md 2009-10-06 14:09:19.767365878 -0700
+@@ -3156,9 +3156,9 @@
+ [(match_parallel 0 "any_parallel_operand"
+ [(clobber (reg:P 65))
+ (use (match_operand:P 1 "symbol_ref_operand" "s"))
+- (use (match_operand:P 2 "gpc_reg_operand" "r"))
+- (set (match_operand:V2SI 3 "memory_operand" "=m")
+- (match_operand:V2SI 4 "gpc_reg_operand" "r"))])]
++ (use (reg:P 11))
++ (set (match_operand:V2SI 2 "memory_operand" "=m")
++ (match_operand:V2SI 3 "gpc_reg_operand" "r"))])]
+ "TARGET_SPE_ABI"
+ "bl %z1"
+ [(set_attr "type" "branch")
+@@ -3168,9 +3168,9 @@
+ [(match_parallel 0 "any_parallel_operand"
+ [(clobber (reg:P 65))
+ (use (match_operand:P 1 "symbol_ref_operand" "s"))
+- (use (match_operand:P 2 "gpc_reg_operand" "r"))
+- (set (match_operand:V2SI 3 "gpc_reg_operand" "=r")
+- (match_operand:V2SI 4 "memory_operand" "m"))])]
++ (use (reg:P 11))
++ (set (match_operand:V2SI 2 "gpc_reg_operand" "=r")
++ (match_operand:V2SI 3 "memory_operand" "m"))])]
+ "TARGET_SPE_ABI"
+ "bl %z1"
+ [(set_attr "type" "branch")
+@@ -3181,9 +3181,9 @@
+ [(return)
+ (clobber (reg:P 65))
+ (use (match_operand:P 1 "symbol_ref_operand" "s"))
+- (use (match_operand:P 2 "gpc_reg_operand" "r"))
+- (set (match_operand:V2SI 3 "gpc_reg_operand" "=r")
+- (match_operand:V2SI 4 "memory_operand" "m"))])]
++ (use (reg:P 11))
++ (set (match_operand:V2SI 2 "gpc_reg_operand" "=r")
++ (match_operand:V2SI 3 "memory_operand" "m"))])]
+ "TARGET_SPE_ABI"
+ "b %z1"
+ [(set_attr "type" "branch")
+Index: gcc-4.4.1/gcc/config/rs6000/linux64.h
+===================================================================
+--- gcc-4.4.1.orig/gcc/config/rs6000/linux64.h 2009-10-06 13:51:50.347316402 -0700
++++ gcc-4.4.1/gcc/config/rs6000/linux64.h 2009-10-06 14:09:19.777366800 -0700
+@@ -433,11 +433,11 @@ extern int dot_symbols;
+ #undef SAVE_FP_PREFIX
+ #define SAVE_FP_PREFIX (TARGET_64BIT ? "._savef" : "_savefpr_")
+ #undef SAVE_FP_SUFFIX
+-#define SAVE_FP_SUFFIX (TARGET_64BIT ? "" : "_l")
++#define SAVE_FP_SUFFIX ""
+ #undef RESTORE_FP_PREFIX
+ #define RESTORE_FP_PREFIX (TARGET_64BIT ? "._restf" : "_restfpr_")
+ #undef RESTORE_FP_SUFFIX
+-#define RESTORE_FP_SUFFIX (TARGET_64BIT ? "" : "_l")
++#define RESTORE_FP_SUFFIX ""
+
+ /* Dwarf2 debugging. */
+ #undef PREFERRED_DEBUGGING_TYPE
+Index: gcc-4.4.1/gcc/config/rs6000/rs6000.c
+===================================================================
+--- gcc-4.4.1.orig/gcc/config/rs6000/rs6000.c 2009-10-06 14:09:04.737313663 -0700
++++ gcc-4.4.1/gcc/config/rs6000/rs6000.c 2009-10-06 14:09:19.797315286 -0700
+@@ -15843,7 +15843,8 @@ static bool
+ no_global_regs_above (int first, bool gpr)
+ {
+ int i;
+- for (i = first; i < gpr ? 32 : 64 ; i++)
++ int last = gpr ? 32 : 64;
++ for (i = first; i < last; i++)
+ if (global_regs[i])
+ return false;
+ return true;
+@@ -15860,54 +15861,136 @@ no_global_regs_above (int first, bool gp
+
+ static GTY(()) rtx savres_routine_syms[N_SAVRES_REGISTERS][8];
+
+-/* Return the symbol for an out-of-line register save/restore routine.
++/* Temporary holding space for an out-of-line register save/restore
++ routine name. */
++static char savres_routine_name[30];
++
++/* Return the name for an out-of-line register save/restore routine.
++ We are saving/restoring GPRs if GPR is true. */
++
++static char *
++rs6000_savres_routine_name (rs6000_stack_t *info, int regno,
++ bool savep, bool gpr, bool lr)
++{
++ const char *prefix = "";
++ const char *suffix = "";
++
++ /* Different targets are supposed to define
++ {SAVE,RESTORE}_FP_{PREFIX,SUFFIX} with the idea that the needed
++ routine name could be defined with:
++
++ sprintf (name, "%s%d%s", SAVE_FP_PREFIX, regno, SAVE_FP_SUFFIX)
++
++ This is a nice idea in practice, but in reality, things are
++ complicated in several ways:
++
++ - ELF targets have save/restore routines for GPRs.
++
++ - SPE targets use different prefixes for 32/64-bit registers, and
++ neither of them fit neatly in the FOO_{PREFIX,SUFFIX} regimen.
++
++ - PPC64 ELF targets have routines for save/restore of GPRs that
++ differ in what they do with the link register, so having a set
++ prefix doesn't work. (We only use one of the save routines at
++ the moment, though.)
++
++ - PPC32 elf targets have "exit" versions of the restore routines
++ that restore the link register and can save some extra space.
++ These require an extra suffix. (There are also "tail" versions
++ of the restore routines and "GOT" versions of the save routines,
++ but we don't generate those at present. Same problems apply,
++ though.)
++
++ We deal with all this by synthesizing our own prefix/suffix and
++ using that for the simple sprintf call shown above. */
++ if (TARGET_SPE)
++ {
++ /* No floating point saves on the SPE. */
++ gcc_assert (gpr);
++
++ if (savep)
++ prefix = info->spe_64bit_regs_used ? "_save64gpr_" : "_save32gpr_";
++ else
++ prefix = info->spe_64bit_regs_used ? "_rest64gpr_" : "_rest32gpr_";
++
++ if (lr)
++ suffix = "_x";
++ }
++ else if (DEFAULT_ABI == ABI_V4)
++ {
++ if (TARGET_64BIT)
++ goto aix_names;
++
++ if (gpr)
++ prefix = savep ? "_savegpr_" : "_restgpr_";
++ else
++ prefix = savep ? "_savefpr_" : "_restfpr_";
++
++ if (lr)
++ suffix = "_x";
++ }
++ else if (DEFAULT_ABI == ABI_AIX)
++ {
++#ifndef POWERPC_LINUX
++ /* No out-of-line save/restore routines for GPRs on AIX. */
++ gcc_assert (!TARGET_AIX || !gpr);
++#endif
++
++ aix_names:
++ if (gpr)
++ prefix = (savep
++ ? (lr ? "_savegpr0_" : "_savegpr1_")
++ : (lr ? "_restgpr0_" : "_restgpr1_"));
++#ifdef POWERPC_LINUX
++ else if (lr)
++ prefix = (savep ? "_savefpr_" : "_restfpr_");
++#endif
++ else
++ {
++ prefix = savep ? SAVE_FP_PREFIX : RESTORE_FP_PREFIX;
++ suffix = savep ? SAVE_FP_SUFFIX : RESTORE_FP_SUFFIX;
++ }
++ }
++ else if (DEFAULT_ABI == ABI_DARWIN)
++ sorry ("Out-of-line save/restore routines not supported on Darwin");
++
++ sprintf (savres_routine_name, "%s%d%s", prefix, regno, suffix);
++
++ return savres_routine_name;
++}
++
++/* Return an RTL SYMBOL_REF for an out-of-line register save/restore routine.
+ We are saving/restoring GPRs if GPR is true. */
+
+ static rtx
+-rs6000_savres_routine_sym (rs6000_stack_t *info, bool savep, bool gpr, bool exitp)
++rs6000_savres_routine_sym (rs6000_stack_t *info, bool savep,
++ bool gpr, bool lr)
+ {
+ int regno = gpr ? info->first_gp_reg_save : (info->first_fp_reg_save - 32);
+ rtx sym;
+ int select = ((savep ? 1 : 0) << 2
+- | (gpr
+- /* On the SPE, we never have any FPRs, but we do have
+- 32/64-bit versions of the routines. */
+- ? (TARGET_SPE_ABI && info->spe_64bit_regs_used ? 1 : 0)
+- : 0) << 1
+- | (exitp ? 1: 0));
++ | ((TARGET_SPE_ABI
++ /* On the SPE, we never have any FPRs, but we do have
++ 32/64-bit versions of the routines. */
++ ? (info->spe_64bit_regs_used ? 1 : 0)
++ : (gpr ? 1 : 0)) << 1)
++ | (lr ? 1: 0));
+
+ /* Don't generate bogus routine names. */
+- gcc_assert (FIRST_SAVRES_REGISTER <= regno && regno <= LAST_SAVRES_REGISTER);
++ gcc_assert (FIRST_SAVRES_REGISTER <= regno
++ && regno <= LAST_SAVRES_REGISTER);
+
+ sym = savres_routine_syms[regno-FIRST_SAVRES_REGISTER][select];
+
+ if (sym == NULL)
+ {
+- char name[30];
+- const char *action;
+- const char *regkind;
+- const char *exit_suffix;
+-
+- action = savep ? "save" : "rest";
+-
+- /* SPE has slightly different names for its routines depending on
+- whether we are saving 32-bit or 64-bit registers. */
+- if (TARGET_SPE_ABI)
+- {
+- /* No floating point saves on the SPE. */
+- gcc_assert (gpr);
+-
+- regkind = info->spe_64bit_regs_used ? "64gpr" : "32gpr";
+- }
+- else
+- regkind = gpr ? "gpr" : "fpr";
+-
+- exit_suffix = exitp ? "_x" : "";
++ char *name;
+
+- sprintf (name, "_%s%s_%d%s", action, regkind, regno, exit_suffix);
++ name = rs6000_savres_routine_name (info, regno, savep, gpr, lr);
+
+ sym = savres_routine_syms[regno-FIRST_SAVRES_REGISTER][select]
+ = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
++ SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_FUNCTION;
+ }
+
+ return sym;
+@@ -15935,8 +16018,13 @@ rs6000_emit_stack_reset (rs6000_stack_t
+ {
+ rs6000_emit_stack_tie ();
+ if (sp_offset != 0)
+- emit_insn (gen_addsi3 (sp_reg_rtx, frame_reg_rtx,
+- GEN_INT (sp_offset)));
++ {
++ rtx dest_reg = savres ? gen_rtx_REG (Pmode, 11) : sp_reg_rtx;
++
++ return emit_insn (gen_addsi3 (dest_reg, frame_reg_rtx,
++ GEN_INT (sp_offset)));
++ }
++
+ else if (!savres)
+ emit_move_insn (sp_reg_rtx, frame_reg_rtx);
+ }
+@@ -15965,7 +16053,7 @@ static rtx
+ rs6000_make_savres_rtx (rs6000_stack_t *info,
+ rtx frame_reg_rtx, int save_area_offset,
+ enum machine_mode reg_mode,
+- bool savep, bool gpr, bool exitp)
++ bool savep, bool gpr, bool lr)
+ {
+ int i;
+ int offset, start_reg, end_reg, n_regs;
+@@ -15979,20 +16067,21 @@ rs6000_make_savres_rtx (rs6000_stack_t *
+ : info->first_fp_reg_save);
+ end_reg = gpr ? 32 : 64;
+ n_regs = end_reg - start_reg;
+- p = rtvec_alloc ((exitp ? 4 : 3) + n_regs);
+-
+- /* If we're saving registers, then we should never say we're exiting. */
+- gcc_assert ((savep && !exitp) || !savep);
++ p = rtvec_alloc ((lr ? 4 : 3) + n_regs);
+
+- if (exitp)
++ if (!savep && lr)
+ RTVEC_ELT (p, offset++) = gen_rtx_RETURN (VOIDmode);
+
+ RTVEC_ELT (p, offset++)
+ = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 65));
+
+- sym = rs6000_savres_routine_sym (info, savep, gpr, exitp);
++ sym = rs6000_savres_routine_sym (info, savep, gpr, lr);
+ RTVEC_ELT (p, offset++) = gen_rtx_USE (VOIDmode, sym);
+- RTVEC_ELT (p, offset++) = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 11));
++ RTVEC_ELT (p, offset++)
++ = gen_rtx_USE (VOIDmode,
++ gen_rtx_REG (Pmode, DEFAULT_ABI != ABI_AIX ? 11
++ : gpr && !lr ? 12
++ : 1));
+
+ for (i = 0; i < end_reg - start_reg; i++)
+ {
+@@ -16007,6 +16096,16 @@ rs6000_make_savres_rtx (rs6000_stack_t *
+ savep ? reg : mem);
+ }
+
++ if (savep && lr)
++ {
++ rtx addr, reg, mem;
++ reg = gen_rtx_REG (Pmode, 0);
++ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
++ GEN_INT (info->lr_save_offset));
++ mem = gen_frame_mem (Pmode, addr);
++ RTVEC_ELT (p, i + offset) = gen_rtx_SET (VOIDmode, mem, reg);
++ }
++
+ return gen_rtx_PARALLEL (VOIDmode, p);
+ }
+
+@@ -16027,7 +16126,10 @@ rs6000_reg_live_or_pic_offset_p (int reg
+ enum {
+ SAVRES_MULTIPLE = 0x1,
+ SAVRES_INLINE_FPRS = 0x2,
+- SAVRES_INLINE_GPRS = 0x4
++ SAVRES_INLINE_GPRS = 0x4,
++ SAVRES_NOINLINE_GPRS_SAVES_LR = 0x8,
++ SAVRES_NOINLINE_FPRS_SAVES_LR = 0x10,
++ SAVRES_NOINLINE_FPRS_DOESNT_RESTORE_LR = 0x20
+ };
+
+ /* Determine the strategy for savings/restoring registers. */
+@@ -16042,6 +16144,7 @@ rs6000_savres_strategy (rs6000_stack_t *
+ bool savres_gprs_inline;
+ bool noclobber_global_gprs
+ = no_global_regs_above (info->first_gp_reg_save, /*gpr=*/true);
++ int strategy;
+
+ using_multiple_p = (TARGET_MULTIPLE && ! TARGET_POWERPC64
+ && (!TARGET_SPE_ABI
+@@ -16061,6 +16164,10 @@ rs6000_savres_strategy (rs6000_stack_t *
+ || info->first_fp_reg_save == 64
+ || !no_global_regs_above (info->first_fp_reg_save,
+ /*gpr=*/false)
++ /* The out-of-line FP routines use
++ double-precision stores; we can't use those
++ routines if we don't have such stores. */
++ || (TARGET_HARD_FLOAT && !TARGET_DOUBLE_FLOAT)
+ || FP_SAVE_INLINE (info->first_fp_reg_save));
+ savres_gprs_inline = (common
+ /* Saving CR interferes with the exit routines
+@@ -16098,9 +16205,22 @@ rs6000_savres_strategy (rs6000_stack_t *
+ savres_gprs_inline = savres_gprs_inline || using_multiple_p;
+ }
+
+- return (using_multiple_p
+- | (savres_fprs_inline << 1)
+- | (savres_gprs_inline << 2));
++ strategy = (using_multiple_p
++ | (savres_fprs_inline << 1)
++ | (savres_gprs_inline << 2));
++#ifdef POWERPC_LINUX
++ if (TARGET_64BIT)
++ {
++ if (!savres_fprs_inline)
++ strategy |= SAVRES_NOINLINE_FPRS_SAVES_LR;
++ else if (!savres_gprs_inline && info->first_fp_reg_save == 64)
++ strategy |= SAVRES_NOINLINE_GPRS_SAVES_LR;
++ }
++#else
++ if (TARGET_AIX && !savres_fprs_inline)
++ strategy |= SAVRES_NOINLINE_FPRS_DOESNT_RESTORE_LR;
++#endif
++ return strategy;
+ }
+
+ /* Emit function prologue as insns. */
+@@ -16122,7 +16242,7 @@ rs6000_emit_prologue (void)
+ int using_store_multiple;
+ int using_static_chain_p = (cfun->static_chain_decl != NULL_TREE
+ && df_regs_ever_live_p (STATIC_CHAIN_REGNUM)
+- && !call_used_regs[STATIC_CHAIN_REGNUM]);
++ && call_used_regs[STATIC_CHAIN_REGNUM]);
+ HOST_WIDE_INT sp_offset = 0;
+
+ if (TARGET_FIX_AND_CONTINUE)
+@@ -16307,24 +16427,30 @@ rs6000_emit_prologue (void)
+ gen_rtx_REG (Pmode, LR_REGNO));
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+- addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
++ if (!(strategy & (SAVRES_NOINLINE_GPRS_SAVES_LR
++ | SAVRES_NOINLINE_FPRS_SAVES_LR)))
++ {
++ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->lr_save_offset + sp_offset));
+- reg = gen_rtx_REG (Pmode, 0);
+- mem = gen_rtx_MEM (Pmode, addr);
+- /* This should not be of rs6000_sr_alias_set, because of
+- __builtin_return_address. */
++ reg = gen_rtx_REG (Pmode, 0);
++ mem = gen_rtx_MEM (Pmode, addr);
++ /* This should not be of rs6000_sr_alias_set, because of
++ __builtin_return_address. */
+
+- insn = emit_move_insn (mem, reg);
+- rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+- NULL_RTX, NULL_RTX);
++ insn = emit_move_insn (mem, reg);
++ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
++ NULL_RTX, NULL_RTX);
++ }
+ }
+
+- /* If we need to save CR, put it into r12. */
++ /* If we need to save CR, put it into r12 or r11. */
+ if (!WORLD_SAVE_P (info) && info->cr_save_p && frame_reg_rtx != frame_ptr_rtx)
+ {
+ rtx set;
+
+- cr_save_rtx = gen_rtx_REG (SImode, 12);
++ cr_save_rtx
++ = gen_rtx_REG (SImode, DEFAULT_ABI == ABI_AIX && !saving_GPRs_inline
++ ? 11 : 12);
+ insn = emit_insn (gen_movesi_from_cr (cr_save_rtx));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ /* Now, there's no way that dwarf2out_frame_debug_expr is going
+@@ -16363,7 +16489,9 @@ rs6000_emit_prologue (void)
+ info->fp_save_offset + sp_offset,
+ DFmode,
+ /*savep=*/true, /*gpr=*/false,
+- /*exitp=*/false);
++ /*lr=*/(strategy
++ & SAVRES_NOINLINE_FPRS_SAVES_LR)
++ != 0);
+ insn = emit_insn (par);
+ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+ NULL_RTX, NULL_RTX);
+@@ -16459,7 +16587,7 @@ rs6000_emit_prologue (void)
+ par = rs6000_make_savres_rtx (info, gen_rtx_REG (Pmode, 11),
+ 0, reg_mode,
+ /*savep=*/true, /*gpr=*/true,
+- /*exitp=*/false);
++ /*lr=*/false);
+ insn = emit_insn (par);
+ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+ NULL_RTX, NULL_RTX);
+@@ -16474,25 +16602,24 @@ rs6000_emit_prologue (void)
+ {
+ rtx par;
+
+- /* Need to adjust r11 if we saved any FPRs. */
++ /* Need to adjust r11 (r12) if we saved any FPRs. */
+ if (info->first_fp_reg_save != 64)
+ {
+- rtx r11 = gen_rtx_REG (reg_mode, 11);
+- rtx offset = GEN_INT (info->total_size
+- + (-8 * (64-info->first_fp_reg_save)));
+- rtx ptr_reg = (sp_reg_rtx == frame_reg_rtx
+- ? sp_reg_rtx : r11);
+-
+- emit_insn (TARGET_32BIT
+- ? gen_addsi3 (r11, ptr_reg, offset)
+- : gen_adddi3 (r11, ptr_reg, offset));
++ rtx dest_reg = gen_rtx_REG (reg_mode, DEFAULT_ABI == ABI_AIX
++ ? 12 : 11);
++ rtx offset = GEN_INT (sp_offset
++ + (-8 * (64-info->first_fp_reg_save)));
++ emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx, offset));
+ }
+
+ par = rs6000_make_savres_rtx (info, frame_reg_rtx,
+ info->gp_save_offset + sp_offset,
+ reg_mode,
+ /*savep=*/true, /*gpr=*/true,
+- /*exitp=*/false);
++ /*lr=*/(strategy
++ & SAVRES_NOINLINE_GPRS_SAVES_LR)
++ != 0);
++
+ insn = emit_insn (par);
+ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+ NULL_RTX, NULL_RTX);
+@@ -16772,9 +16899,18 @@ rs6000_output_function_prologue (FILE *f
+ fp values. */
+ if (info->first_fp_reg_save < 64
+ && !FP_SAVE_INLINE (info->first_fp_reg_save))
+- fprintf (file, "\t.extern %s%d%s\n\t.extern %s%d%s\n",
+- SAVE_FP_PREFIX, info->first_fp_reg_save - 32, SAVE_FP_SUFFIX,
+- RESTORE_FP_PREFIX, info->first_fp_reg_save - 32, RESTORE_FP_SUFFIX);
++ {
++ char *name;
++ int regno = info->first_fp_reg_save - 32;
++
++ name = rs6000_savres_routine_name (info, regno, /*savep=*/true,
++ /*gpr=*/false, /*lr=*/false);
++ fprintf (file, "\t.extern %s\n", name);
++
++ name = rs6000_savres_routine_name (info, regno, /*savep=*/false,
++ /*gpr=*/false, /*lr=*/true);
++ fprintf (file, "\t.extern %s\n", name);
++ }
+
+ /* Write .extern for AIX common mode routines, if needed. */
+ if (! TARGET_POWER && ! TARGET_POWERPC && ! common_mode_defined)
+@@ -16891,6 +17027,7 @@ rs6000_emit_epilogue (int sibcall)
+ int sp_offset = 0;
+ rtx sp_reg_rtx = gen_rtx_REG (Pmode, 1);
+ rtx frame_reg_rtx = sp_reg_rtx;
++ rtx cr_save_reg = NULL_RTX;
+ enum machine_mode reg_mode = Pmode;
+ int reg_size = TARGET_32BIT ? 4 : 8;
+ int i;
+@@ -16924,8 +17061,10 @@ rs6000_emit_epilogue (int sibcall)
+ || (cfun->calls_alloca
+ && !frame_pointer_needed));
+ restore_lr = (info->lr_save_p
+- && restoring_GPRs_inline
+- && restoring_FPRs_inline);
++ && (restoring_FPRs_inline
++ || (strategy & SAVRES_NOINLINE_FPRS_DOESNT_RESTORE_LR))
++ && (restoring_GPRs_inline
++ || info->first_fp_reg_save < 64));
+
+ if (WORLD_SAVE_P (info))
+ {
+@@ -17197,7 +17336,7 @@ rs6000_emit_epilogue (int sibcall)
+
+ /* Get the old lr if we saved it. If we are restoring registers
+ out-of-line, then the out-of-line routines can do this for us. */
+- if (restore_lr)
++ if (restore_lr && restoring_GPRs_inline)
+ {
+ rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx,
+ info->lr_save_offset + sp_offset);
+@@ -17211,12 +17350,17 @@ rs6000_emit_epilogue (int sibcall)
+ rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->cr_save_offset + sp_offset));
+ rtx mem = gen_frame_mem (SImode, addr);
++ cr_save_reg = gen_rtx_REG (SImode,
++ DEFAULT_ABI == ABI_AIX
++ && !restoring_GPRs_inline
++ && info->first_fp_reg_save < 64
++ ? 11 : 12);
++ emit_move_insn (cr_save_reg, mem);
+
+- emit_move_insn (gen_rtx_REG (SImode, 12), mem);
+ }
+
+ /* Set LR here to try to overlap restores below. */
+- if (restore_lr)
++ if (restore_lr && restoring_GPRs_inline)
+ emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO),
+ gen_rtx_REG (Pmode, 0));
+
+@@ -17318,7 +17462,7 @@ rs6000_emit_epilogue (int sibcall)
+ par = rs6000_make_savres_rtx (info, gen_rtx_REG (Pmode, 11),
+ 0, reg_mode,
+ /*savep=*/false, /*gpr=*/true,
+- /*exitp=*/true);
++ /*lr=*/true);
+ emit_jump_insn (par);
+
+ /* We don't want anybody else emitting things after we jumped
+@@ -17337,20 +17481,24 @@ rs6000_emit_epilogue (int sibcall)
+ rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx,
+ sp_offset, can_use_exit);
+ else
+- emit_insn (gen_addsi3 (gen_rtx_REG (Pmode, 11),
+- sp_reg_rtx,
+- GEN_INT (sp_offset - info->fp_size)));
++ {
++ emit_insn (gen_add3_insn (gen_rtx_REG (Pmode, DEFAULT_ABI == ABI_AIX
++ ? 12 : 11),
++ frame_reg_rtx,
++ GEN_INT (sp_offset - info->fp_size)));
++ if (REGNO (frame_reg_rtx) == 11)
++ sp_offset += info->fp_size;
++ }
+
+ par = rs6000_make_savres_rtx (info, frame_reg_rtx,
+ info->gp_save_offset, reg_mode,
+ /*savep=*/false, /*gpr=*/true,
+- /*exitp=*/can_use_exit);
++ /*lr=*/can_use_exit);
+
+ if (can_use_exit)
+ {
+ if (info->cr_save_p)
+- rs6000_restore_saved_cr (gen_rtx_REG (SImode, 12),
+- using_mtcr_multiple);
++ rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
+
+ emit_jump_insn (par);
+
+@@ -17396,6 +17544,16 @@ rs6000_emit_epilogue (int sibcall)
+ }
+ }
+
++ if (restore_lr && !restoring_GPRs_inline)
++ {
++ rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx,
++ info->lr_save_offset + sp_offset);
++
++ emit_move_insn (gen_rtx_REG (Pmode, 0), mem);
++ emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO),
++ gen_rtx_REG (Pmode, 0));
++ }
++
+ /* Restore fpr's if we need to do it without calling a function. */
+ if (restoring_FPRs_inline)
+ for (i = 0; i < 64 - info->first_fp_reg_save; i++)
+@@ -17419,7 +17577,7 @@ rs6000_emit_epilogue (int sibcall)
+
+ /* If we saved cr, restore it here. Just those that were used. */
+ if (info->cr_save_p)
+- rs6000_restore_saved_cr (gen_rtx_REG (SImode, 12), using_mtcr_multiple);
++ rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
+
+ /* If this is V.4, unwind the stack pointer after all of the loads
+ have been done. */
+@@ -17437,13 +17595,14 @@ rs6000_emit_epilogue (int sibcall)
+ if (!sibcall)
+ {
+ rtvec p;
++ bool lr = (strategy & SAVRES_NOINLINE_FPRS_DOESNT_RESTORE_LR) == 0;
+ if (! restoring_FPRs_inline)
+ p = rtvec_alloc (4 + 64 - info->first_fp_reg_save);
+ else
+ p = rtvec_alloc (2);
+
+ RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
+- RTVEC_ELT (p, 1) = (restoring_FPRs_inline
++ RTVEC_ELT (p, 1) = ((restoring_FPRs_inline || !lr)
+ ? gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 65))
+ : gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_REG (Pmode, 65)));
+@@ -17458,10 +17617,12 @@ rs6000_emit_epilogue (int sibcall)
+ sym = rs6000_savres_routine_sym (info,
+ /*savep=*/false,
+ /*gpr=*/false,
+- /*exitp=*/true);
++ /*lr=*/lr);
+ RTVEC_ELT (p, 2) = gen_rtx_USE (VOIDmode, sym);
+ RTVEC_ELT (p, 3) = gen_rtx_USE (VOIDmode,
+- gen_rtx_REG (Pmode, 11));
++ gen_rtx_REG (Pmode,
++ DEFAULT_ABI == ABI_AIX
++ ? 1 : 11));
+ for (i = 0; i < 64 - info->first_fp_reg_save; i++)
+ {
+ rtx addr, mem;
+Index: gcc-4.4.1/gcc/config/rs6000/rs6000.md
+===================================================================
+--- gcc-4.4.1.orig/gcc/config/rs6000/rs6000.md 2009-10-06 14:09:12.087313658 -0700
++++ gcc-4.4.1/gcc/config/rs6000/rs6000.md 2009-10-06 14:09:19.797315286 -0700
+@@ -14868,6 +14868,19 @@
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
++(define_insn "*return_and_restore_fpregs_aix_<mode>"
++ [(match_parallel 0 "any_parallel_operand"
++ [(return)
++ (use (match_operand:P 1 "register_operand" "l"))
++ (use (match_operand:P 2 "symbol_ref_operand" "s"))
++ (use (match_operand:P 3 "gpc_reg_operand" "r"))
++ (set (match_operand:DF 4 "gpc_reg_operand" "=d")
++ (match_operand:DF 5 "memory_operand" "m"))])]
++ ""
++ "b %z2"
++ [(set_attr "type" "branch")
++ (set_attr "length" "4")])
++
+ ; This is used in compiling the unwind routines.
+ (define_expand "eh_return"
+ [(use (match_operand 0 "general_operand" ""))]
+Index: gcc-4.4.1/gcc/config/rs6000/sysv4.h
+===================================================================
+--- gcc-4.4.1.orig/gcc/config/rs6000/sysv4.h 2009-10-06 13:51:50.447316469 -0700
++++ gcc-4.4.1/gcc/config/rs6000/sysv4.h 2009-10-06 14:09:19.807390239 -0700
+@@ -271,27 +271,25 @@ do { \
+ #endif
+
+ /* Define cutoff for using external functions to save floating point.
+- Currently on 64-bit V.4, always use inline stores. When optimizing
+- for size on 32-bit targets, use external functions when
+- profitable. */
+-#define FP_SAVE_INLINE(FIRST_REG) (optimize_size && !TARGET_64BIT \
++ When optimizing for size, use external functions when profitable. */
++#define FP_SAVE_INLINE(FIRST_REG) (optimize_size \
+ ? ((FIRST_REG) == 62 \
+ || (FIRST_REG) == 63) \
+ : (FIRST_REG) < 64)
+ /* And similarly for general purpose registers. */
+ #define GP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 32 \
+- && (TARGET_64BIT || !optimize_size))
++ && !optimize_size)
+
+ /* Put jump tables in read-only memory, rather than in .text. */
+ #define JUMP_TABLES_IN_TEXT_SECTION 0
+
+ /* Prefix and suffix to use to saving floating point. */
+ #define SAVE_FP_PREFIX "_savefpr_"
+-#define SAVE_FP_SUFFIX (TARGET_64BIT ? "_l" : "")
++#define SAVE_FP_SUFFIX ""
+
+ /* Prefix and suffix to use to restoring floating point. */
+ #define RESTORE_FP_PREFIX "_restfpr_"
+-#define RESTORE_FP_SUFFIX (TARGET_64BIT ? "_l" : "")
++#define RESTORE_FP_SUFFIX ""
+
+ /* Type used for ptrdiff_t, as a string used in a declaration. */
+ #define PTRDIFF_TYPE "int"