(function units): Numerous cycle count change.
authorRichard Kenner <kenner@gcc.gnu.org>
Thu, 12 May 1994 23:33:39 +0000 (19:33 -0400)
committerRichard Kenner <kenner@gcc.gnu.org>
Thu, 12 May 1994 23:33:39 +0000 (19:33 -0400)
(zero_extendqidi2, extendqidi2, zero_extendhidi2): New patterns.
(extendhidi2, zero_extendsidi2, extendsidi2): Likewise.
(zero_extendqisi2, zero_extendqihi2, zero_extendhisi2): Use
andil/andi instead of rlinm/rlwinm.
(zero_extendqihi2): Add condition register variants.
(extendqisi2, extendqihi2): Use extsb for PowerPC.
(adddi3, subdi3, negdi2, ashrdi3): Emulate only if !TARGET_POWERPC64.
(movdf, movdi, movti): New PowerPC64 versions.
(load/store with update): New PowerPC64 patterns.

From-SVN: r7288

gcc/config/rs6000/rs6000.md

index 69c2a617b03baa7e02594537bb0a82f155dde48a..3796e5eac867fc339c85b1978b09430fc5bd1da9 100644 (file)
@@ -45,6 +45,8 @@
 ; (define_function_unit NAME MULTIPLICITY SIMULTANEITY
 ;                      TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST])
 
+; Load/Store Unit -- POWER/2 and pure PowerPC only
+; (POWER and 601 use Integer Unit)
 (define_function_unit "lsu" 1 0
   (and (eq_attr "type" "load")
        (eq_attr "cpu" "rios2,ppc603,ppc604,ppc620"))
        (eq_attr "cpu" "rios1,ppc601"))
   3 0)
 
+; Integer Unit (RIOS1, PPC601, PPC603)
+; Trivial operations take one cycle which need not be listed here.
 (define_function_unit "iu" 1 0
   (and (eq_attr "type" "imul")
        (eq_attr "cpu" "rios1"))
-  3 0)
+  3 3)
 
 (define_function_unit "iu" 1 0
   (and (eq_attr "type" "imul")
-       (eq_attr "cpu" "ppc601,ppc603,ppc604,ppc620"))
-  5 0)
+       (eq_attr "cpu" "ppc601,ppc603"))
+  5 5)
 
 (define_function_unit "iu" 1 0
   (and (eq_attr "type" "idiv")
        (eq_attr "cpu" "rios1"))
-  19 0)
+  19 19)
 
 (define_function_unit "iu" 1 0
   (and (eq_attr "type" "idiv")
-       (eq_attr "cpu" "ppc601,ppc603,ppc604,ppc620"))
-  36 0)
+       (eq_attr "cpu" "ppc601"))
+  36 36)
+
+(define_function_unit "iu" 1 0
+  (and (eq_attr "type" "idiv")
+       (eq_attr "cpu" "ppc603"))
+  37 36)
+
+; RIOS2 has two integer units: a primary one which can perform all
+; operations and a secondary one which is fed in lock step with the first
+; and can perform "simple" integer operations.
+(define_function_unit "iu2" 2 0
+  (and (eq_attr "type" "integer")
+       (eq_attr "cpu" "rios2"))
+  1 0
+  [(eq_attr "type" "imul,idiv")])
+
+(define_function_unit "imuldiv" 1 0
+  (and (eq_attr "type" "imul")
+       (eq_attr "cpu" "rios2"))
+  2 2
+  [(eq_attr "type" "integer")])
+
+(define_function_unit "imuldiv" 1 0
+  (and (eq_attr "type" "idiv")
+       (eq_attr "cpu" "rios2"))
+  13 13
+  [(eq_attr "type" "integer")])
+
+; PPC604 has three integer units: one primary and two secondary.
+(define_function_unit "iu3" 3 0
+  (and (eq_attr "type" "integer")
+       (eq_attr "cpu" "ppc604,ppc620"))
+  1 0
+  [(eq_attr "type" "imul,idiv")])
+
+(define_function_unit "imuldiv" 1 0
+  (and (eq_attr "type" "imul")
+       (eq_attr "cpu" "ppc604,ppc620"))
+  4 2
+  [(eq_attr "type" "integer")])
+
+(define_function_unit "imuldiv" 1 0
+  (and (eq_attr "type" "idiv")
+       (eq_attr "cpu" "ppc604,ppc620"))
+  20 19
+  [(eq_attr "type" "integer")])
 
+; Branch Processing Unit
 (define_function_unit "bpu" 1 0
   (eq_attr "type" "compare")
   4 0)
        (eq_attr "cpu" "ppc601,ppc603,ppc604,ppc620"))
   4 0)
 
+; Floating Point Unit (RIOS1, PPC601, PPC603, PPC604).
 (define_function_unit "fpu" 1 0
-  (and (eq_attr "type" "fp")
+  (and (eq_attr "type" "fp,dmul")
        (eq_attr "cpu" "rios1"))
   2 0)
 
 (define_function_unit "fpu" 1 0
   (and (eq_attr "type" "fp")
-       (eq_attr "cpu" "ppc601,ppc603,ppc604,ppc620"))
+       (eq_attr "cpu" "ppc601"))
   4 0)
 
+(define_function_unit "fpu" 1 0
+  (and (eq_attr "type" "fp")
+       (eq_attr "cpu" "ppc603,ppc604,ppc620"))
+  3 0)
+
 (define_function_unit "fpu" 1 0
   (and (eq_attr "type" "dmul")
-       (eq_attr "cpu" "rios1"))
-  2 0)
+       (eq_attr "cpu" "ppc601"))
+  5 5)
 
 (define_function_unit "fpu" 1 0
   (and (eq_attr "type" "dmul")
-       (eq_attr "cpu" "ppc601,ppc603,ppc604,ppc620"))
-  5 0)
+       (eq_attr "cpu" "ppc603"))
+  4 2)
 
 (define_function_unit "fpu" 1 0
-  (and (eq_attr "type" "sdiv")
+  (and (eq_attr "type" "dmul")
+       (eq_attr "cpu" "ppc604,ppc620"))
+  3 0)
+
+(define_function_unit "fpu" 1 0
+  (and (eq_attr "type" "sdiv,ddiv")
        (eq_attr "cpu" "rios1"))
-  19 0)
+  19 19)
 
 (define_function_unit "fpu" 1 0
   (and (eq_attr "type" "sdiv")
-       (eq_attr "cpu" "ppc601,ppc603,ppc604,ppc620"))
-  17 0)
+       (eq_attr "cpu" "ppc601"))
+  17 17)
+
+(define_function_unit "fpu" 1 0
+  (and (eq_attr "type" "sdiv")
+       (eq_attr "cpu" "ppc603,ppc604,ppc620"))
+  18 18)
 
 (define_function_unit "fpu" 1 0
   (and (eq_attr "type" "ddiv")
-       (eq_attr "cpu" "rios1"))
-  19 0)
+       (eq_attr "cpu" "ppc601,ppc604,ppc620"))
+  31 31)
 
 (define_function_unit "fpu" 1 0
   (and (eq_attr "type" "ddiv")
-       (eq_attr "cpu" "ppc601,ppc603,ppc604,ppc620"))
-  31 0)
+       (eq_attr "cpu" "ppc603"))
+  33 33)
 
 (define_function_unit "fpu" 1 0
   (and (eq_attr "type" "ssqrt")
-       (eq_attr "cpu" "ppc603,ppc604,ppc620"))
-  31 0)
+       (eq_attr "cpu" "ppc604,ppc620"))
+  31 31)
 
 (define_function_unit "fpu" 1 0
   (and (eq_attr "type" "dsqrt")
-       (eq_attr "cpu" "ppc603,ppc604,ppc620"))
-  31 0)
-
-(define_function_unit "iu2" 2 0
-  (and (eq_attr "type" "integer")
-       (eq_attr "cpu" "rios2"))
-  1 0
-  [(eq_attr "type" "imul,idiv")])
-
-(define_function_unit "imuldiv" 1 0
-  (and (eq_attr "type" "imul")
-       (eq_attr "cpu" "rios2"))
-  2 0
-  [(eq_attr "type" "integer")])
-
-(define_function_unit "imuldiv" 1 0
-  (and (eq_attr "type" "idiv")
-       (eq_attr "cpu" "rios2"))
-  13 0
-  [(eq_attr "type" "integer")])
+       (eq_attr "cpu" "ppc604,ppc620"))
+  31 31)
 
+; RIOS2 has two symmetric FPUs.
 (define_function_unit "fpu2" 2 0
   (and (eq_attr "type" "fp")
        (eq_attr "cpu" "rios2"))
   2 0)
 
 (define_function_unit "fpu2" 2 0
-  (and (eq_attr "type" "sdiv")
-       (eq_attr "cpu" "rios2"))
-  17 0)
-
-(define_function_unit "fpu2" 2 0
-  (and (eq_attr "type" "ddiv")
+  (and (eq_attr "type" "sdiv,ddiv")
        (eq_attr "cpu" "rios2"))
-  17 0)
+  17 17)
 
 (define_function_unit "fpu2" 2 0
-  (and (eq_attr "type" "ssqrt")
+  (and (eq_attr "type" "ssqrt,dsqrt")
        (eq_attr "cpu" "rios2"))
-  26 0)
-
-(define_function_unit "fpu2" 2 0
-  (and (eq_attr "type" "dsqrt")
-       (eq_attr "cpu" "rios2"))
-  26 0)
+  26 26)
 \f
 ;; Start with fixed-point load and store insns.  Here we put only the more
 ;; complex forms.  Basic data transfer is done later.
 
+(define_expand "zero_extendqidi2"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+       (zero_extend:DI (match_operand:QI 1 "gpc_reg_operand" "")))]
+  "TARGET_POWERPC64"
+  "")
+
+(define_insn ""
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (zero_extend:DI (match_operand:QI 1 "reg_or_mem_operand" "m,r")))]
+  "TARGET_POWERPC64"
+  "@
+   lbz%U1%X1 %0,%1
+   andi %0,%1,0xff"
+  [(set_attr "type" "load,*")])
+
+(define_insn ""
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+       (compare:CC (zero_extend:DI (match_operand:QI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 2 "=r"))]
+  ""
+  "andi. %2,%1,0xff"
+  [(set_attr "type" "compare")])
+
+(define_insn ""
+  [(set (match_operand:CC 2 "cc_reg_operand" "=x")
+       (compare:CC (zero_extend:DI (match_operand:QI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI (match_dup 1)))]
+  ""
+  "andi. %0,%1,0xff"
+  [(set_attr "type" "compare")])
+
+(define_expand "extendqidi2"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+       (sign_extend:DI (match_operand:QI 1 "gpc_reg_operand" "")))]
+  "TARGET_POWERPC64"
+  "")
+
+(define_insn ""
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (sign_extend:DI (match_operand:QI 1 "reg_or_mem_operand" "m,r")))]
+  "TARGET_POWERPC64"
+  "@
+   lba%U1%X1 %0,%1
+   extsb %0,%1"
+  [(set_attr "type" "load,*")])
+
+(define_insn ""
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+       (compare:CC (sign_extend:DI (match_operand:QI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 2 "=r"))]
+  "TARGET_POWERPC64"
+  "extsb. %2,%1"
+  [(set_attr "type" "compare")])
+
+(define_insn ""
+  [(set (match_operand:CC 2 "cc_reg_operand" "=x")
+       (compare:CC (sign_extend:DI (match_operand:QI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (sign_extend:DI (match_dup 1)))]
+  "TARGET_POWERPC64"
+  "extsb. %0,%1"
+  [(set_attr "type" "compare")])
+
+(define_expand "zero_extendhidi2"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+       (zero_extend:DI (match_operand:HI 1 "gpc_reg_operand" "")))]
+  "TARGET_POWERPC64"
+  "")
+
+(define_insn ""
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (zero_extend:DI (match_operand:HI 1 "reg_or_mem_operand" "m,r")))]
+  "TARGET_POWERPC64"
+  "@
+   lhz%U1%X1 %0,%1
+   andi %0,%1,0xffff"
+  [(set_attr "type" "load,*")])
+
+(define_insn ""
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+       (compare:CC (zero_extend:DI (match_operand:HI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 2 "=r"))]
+  "TARGET_POWERPC64"
+  "andi. %2,%1,0xffff"
+  [(set_attr "type" "compare")])
+
+(define_insn ""
+  [(set (match_operand:CC 2 "cc_reg_operand" "=x")
+       (compare:CC (zero_extend:DI (match_operand:HI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI (match_dup 1)))]
+  "TARGET_POWERPC64"
+  "andi. %0,%1,0xffff"
+  [(set_attr "type" "compare")])
+
+(define_expand "extendhidi2"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+       (sign_extend:DI (match_operand:HI 1 "gpc_reg_operand" "")))]
+  "TARGET_POWERPC64"
+  "")
+
+(define_insn ""
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (sign_extend:DI (match_operand:HI 1 "reg_or_mem_operand" "m,r")))]
+  "TARGET_POWERPC64"
+  "@
+   lha%U1%X1 %0,%1
+   extsh %0,%1"
+  [(set_attr "type" "load,*")])
+
+(define_insn ""
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+       (compare:CC (sign_extend:DI (match_operand:HI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 2 "=r"))]
+  "TARGET_POWERPC64"
+  "extsh. %2,%1"
+  [(set_attr "type" "compare")])
+
+(define_insn ""
+  [(set (match_operand:CC 2 "cc_reg_operand" "=x")
+       (compare:CC (sign_extend:DI (match_operand:HI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (sign_extend:DI (match_dup 1)))]
+  "TARGET_POWERPC64"
+  "extsh. %0,%1"
+  [(set_attr "type" "compare")])
+
+(define_expand "zero_extendsidi2"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+       (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "")))]
+  "TARGET_POWERPC64"
+  "")
+
+(define_insn ""
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (zero_extend:DI (match_operand:SI 1 "reg_or_mem_operand" "m,r")))]
+  "TARGET_POWERPC64"
+  "@
+   lwz%U1%X1 %0,%1
+   rldicl %0,%1,0,32"
+  [(set_attr "type" "load,*")])
+
+(define_insn ""
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+       (compare:CC (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 2 "=r"))]
+  "TARGET_POWERPC64"
+  "rldicl. %2,%1,0,32"
+  [(set_attr "type" "compare")])
+
+(define_insn ""
+  [(set (match_operand:CC 2 "cc_reg_operand" "=x")
+       (compare:CC (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (zero_extend:DI (match_dup 1)))]
+  "TARGET_POWERPC64"
+  "rldicl. %0,%1,0,32"
+  [(set_attr "type" "compare")])
+
+(define_expand "extendsidi2"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+       (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "")))]
+  "TARGET_POWERPC64"
+  "")
+
+(define_insn ""
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+       (sign_extend:DI (match_operand:SI 1 "reg_or_mem_operand" "m,r")))]
+  "TARGET_POWERPC64"
+  "@
+   lwa%U1%X1 %0,%1
+   extsw %0,%1"
+  [(set_attr "type" "load,*")])
+
+(define_insn ""
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+       (compare:CC (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (clobber (match_scratch:DI 2 "=r"))]
+  "TARGET_POWERPC64"
+  "extsw. %2,%1"
+  [(set_attr "type" "compare")])
+
+(define_insn ""
+  [(set (match_operand:CC 2 "cc_reg_operand" "=x")
+       (compare:CC (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (sign_extend:DI (match_dup 1)))]
+  "TARGET_POWERPC64"
+  "extsw. %0,%1"
+  [(set_attr "type" "compare")])
+
 (define_expand "zero_extendqisi2"
   [(set (match_operand:SI 0 "gpc_reg_operand" "")
        (zero_extend:SI (match_operand:QI 1 "gpc_reg_operand" "")))]
   ""
   "@
    lbz%U1%X1 %0,%1
-   {rlinm|rlwinm} %0,%1,0,0xff"
+   {andil|andi} %0,%1,0xff"
   [(set_attr "type" "load,*")])
 
 (define_insn ""
   "{andil.|andi.} %0,%1,0xff"
   [(set_attr "type" "compare")])
 
+(define_expand "extendqisi2"
+  [(use (match_operand:SI 0 "gpc_reg_operand" ""))
+   (use (match_operand:QI 1 "gpc_reg_operand" ""))]
+  ""
+  "
+{
+  if (TARGET_POWERPC)
+    emit_insn (gen_extendqisi2_ppc (operands[0], operands[1]));
+  else if (TARGET_POWER)
+    emit_insn (gen_extendqisi2_power (operands[0], operands[1]));
+  else
+    emit_insn (gen_extendqisi2_no_power (operands[0], operands[1]));
+  DONE;
+}")
+
+(define_insn "extendqisi2_ppc"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+       (sign_extend:SI (match_operand:QI 1 "reg_or_mem_operand" "m,r")))]
+  "TARGET_POWERPC"
+  "@
+   lba%U1%X1 %0,%1
+   extsb %0,%1"
+  [(set_attr "type" "load,*")])
+
+(define_insn ""
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+       (compare:CC (sign_extend:SI (match_operand:QI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (clobber (match_scratch:SI 2 "=r"))]
+  "TARGET_POWERPC"
+  "extsb. %2,%1"
+  [(set_attr "type" "compare")])
+
+(define_insn ""
+  [(set (match_operand:CC 2 "cc_reg_operand" "=x")
+       (compare:CC (sign_extend:SI (match_operand:QI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (sign_extend:SI (match_dup 1)))]
+  "TARGET_POWERPC"
+  "extsb. %0,%1"
+  [(set_attr "type" "compare")])
+
+(define_expand "extendqisi2_power"
+  [(parallel [(set (match_dup 2)
+                  (ashift:SI (match_operand:QI 1 "gpc_reg_operand" "")
+                             (const_int 24)))
+             (clobber (scratch:SI))])
+   (parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
+                  (ashiftrt:SI (match_dup 2)
+                               (const_int 24)))
+             (clobber (scratch:SI))])]
+  "TARGET_POWER"
+  "
+{ operands[1] = gen_lowpart (SImode, operands[1]);
+  operands[2] = gen_reg_rtx (SImode); }")
+
+(define_expand "extendqisi2_no_power"
+  [(set (match_dup 2)
+       (ashift:SI (match_operand:QI 1 "gpc_reg_operand" "")
+                  (const_int 24)))
+   (set (match_operand:SI 0 "gpc_reg_operand" "")
+       (ashiftrt:SI (match_dup 2)
+                    (const_int 24)))]
+  "! TARGET_POWER && ! TARGET_POWERPC"
+  "
+{ operands[1] = gen_lowpart (SImode, operands[1]);
+  operands[2] = gen_reg_rtx (SImode); }")
+
 (define_expand "zero_extendqihi2"
   [(set (match_operand:HI 0 "gpc_reg_operand" "")
        (zero_extend:HI (match_operand:QI 1 "gpc_reg_operand" "")))]
   ""
   "@
    lbz%U1%X1 %0,%1
-   {rlinm|rlwinm} %0,%1,0,0xff"
+   {andil|andi} %0,%1,0xff"
+  [(set_attr "type" "load,*")])
+
+(define_insn ""
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+       (compare:CC (zero_extend:HI (match_operand:QI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (clobber (match_scratch:HI 2 "=r"))]
+  ""
+  "{andil.|andi.} %2,%1,0xff"
+  [(set_attr "type" "compare")])
+
+(define_insn ""
+  [(set (match_operand:CC 2 "cc_reg_operand" "=x")
+       (compare:CC (zero_extend:HI (match_operand:QI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (set (match_operand:HI 0 "gpc_reg_operand" "=r")
+       (zero_extend:HI (match_dup 1)))]
+  ""
+  "{andil.|andi.} %0,%1,0xff"
+  [(set_attr "type" "compare")])
+
+(define_expand "extendqihi2"
+  [(use (match_operand:HI 0 "gpc_reg_operand" ""))
+   (use (match_operand:QI 1 "gpc_reg_operand" ""))]
+  ""
+  "
+{
+  if (TARGET_POWERPC)
+    emit_insn (gen_extendqihi2_ppc (operands[0], operands[1]));
+  else if (TARGET_POWER)
+    emit_insn (gen_extendqihi2_power (operands[0], operands[1]));
+  else
+    emit_insn (gen_extendqihi2_no_power (operands[0], operands[1]));
+  DONE;
+}")
+
+(define_insn "extendqihi2_ppc"
+  [(set (match_operand:HI 0 "gpc_reg_operand" "=r,r")
+       (sign_extend:HI (match_operand:QI 1 "reg_or_mem_operand" "m,r")))]
+  "TARGET_POWERPC"
+  "@
+   lba%U1%X1 %0,%1
+   extsb %0,%1"
   [(set_attr "type" "load,*")])
 
+(define_insn ""
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+       (compare:CC (sign_extend:HI (match_operand:QI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (clobber (match_scratch:HI 2 "=r"))]
+  "TARGET_POWERPC"
+  "extsb. %2,%1"
+  [(set_attr "type" "compare")])
+
+(define_insn ""
+  [(set (match_operand:CC 2 "cc_reg_operand" "=x")
+       (compare:CC (sign_extend:HI (match_operand:QI 1 "gpc_reg_operand" "r"))
+                   (const_int 0)))
+   (set (match_operand:HI 0 "gpc_reg_operand" "=r")
+       (sign_extend:HI (match_dup 1)))]
+  "TARGET_POWERPC"
+  "extsb. %0,%1"
+  [(set_attr "type" "compare")])
+
+(define_expand "extendqihi2_power"
+  [(parallel [(set (match_dup 2)
+                  (ashift:SI (match_operand:QI 1 "gpc_reg_operand" "")
+                             (const_int 24)))
+             (clobber (scratch:SI))])
+   (parallel [(set (match_operand:HI 0 "gpc_reg_operand" "")
+                  (ashiftrt:SI (match_dup 2)
+                               (const_int 24)))
+             (clobber (scratch:SI))])]
+  "TARGET_POWER"
+  "
+{ operands[0] = gen_lowpart (SImode, operands[0]);
+  operands[1] = gen_lowpart (SImode, operands[1]);
+  operands[2] = gen_reg_rtx (SImode); }")
+
+(define_expand "extendqihi2_no_power"
+  [(set (match_dup 2)
+       (ashift:SI (match_operand:QI 1 "gpc_reg_operand" "")
+                  (const_int 24)))
+   (set (match_operand:HI 0 "gpc_reg_operand" "")
+       (ashiftrt:SI (match_dup 2)
+                    (const_int 24)))]
+  "! TARGET_POWER && ! TARGET_POWERPC"
+  "
+{ operands[0] = gen_lowpart (SImode, operands[0]);
+  operands[1] = gen_lowpart (SImode, operands[1]);
+  operands[2] = gen_reg_rtx (SImode); }")
+
 (define_expand "zero_extendhisi2"
   [(set (match_operand:SI 0 "gpc_reg_operand" "")
        (zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" "")))]
   ""
   "@
    lhz%U1%X1 %0,%1
-   {rlinm|rlwinm} %0,%1,0,0xffff"
+   {andil|andi} %0,%1,0xffff"
   [(set_attr "type" "load,*")])
 
 (define_insn ""
   "! TARGET_POWER"
   "sraw%I2. %0,%1,%2"
   [(set_attr "type" "delayed_compare")])
-
-(define_expand "extendqisi2"
-  [(use (match_operand:SI 0 "gpc_reg_operand" ""))
-   (use (match_operand:QI 1 "gpc_reg_operand" ""))]
-  ""
-  "
-{
-  if (TARGET_POWER)
-    emit_insn (gen_extendqisi2_power (operands[0], operands[1]));
-  else
-    emit_insn (gen_extendqisi2_no_power (operands[0], operands[1]));
-  DONE;
-}")
-
-(define_expand "extendqisi2_power"
-  [(parallel [(set (match_dup 2)
-                  (ashift:SI (match_operand:QI 1 "gpc_reg_operand" "")
-                             (const_int 24)))
-             (clobber (scratch:SI))])
-   (parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
-                  (ashiftrt:SI (match_dup 2)
-                               (const_int 24)))
-             (clobber (scratch:SI))])]
-  "TARGET_POWER"
-  "
-{ operands[1] = gen_lowpart (SImode, operands[1]);
-  operands[2] = gen_reg_rtx (SImode); }")
-
-(define_expand "extendqisi2_no_power"
-  [(set (match_dup 2)
-                  (ashift:SI (match_operand:QI 1 "gpc_reg_operand" "")
-                             (const_int 24)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-                  (ashiftrt:SI (match_dup 2)
-                               (const_int 24)))]
-  "! TARGET_POWER"
-  "
-{ operands[1] = gen_lowpart (SImode, operands[1]);
-  operands[2] = gen_reg_rtx (SImode); }")
-
-(define_expand "extendqihi2"
-  [(use (match_operand:HI 0 "gpc_reg_operand" ""))
-   (use (match_operand:QI 1 "gpc_reg_operand" ""))]
-  ""
-  "
-{
-  if (TARGET_POWER)
-    emit_insn (gen_extendqihi2_power (operands[0], operands[1]));
-  else
-    emit_insn (gen_extendqihi2_no_power (operands[0], operands[1]));
-  DONE;
-}")
-
-(define_expand "extendqihi2_power"
-  [(parallel [(set (match_dup 2)
-                  (ashift:SI (match_operand:QI 1 "gpc_reg_operand" "")
-                             (const_int 24)))
-             (clobber (scratch:SI))])
-   (parallel [(set (match_operand:HI 0 "gpc_reg_operand" "")
-                  (ashiftrt:SI (match_dup 2)
-                               (const_int 24)))
-             (clobber (scratch:SI))])]
-  "TARGET_POWER"
-  "
-{ operands[0] = gen_lowpart (SImode, operands[0]);
-  operands[1] = gen_lowpart (SImode, operands[1]);
-  operands[2] = gen_reg_rtx (SImode); }")
-
-(define_expand "extendqihi2_no_power"
-  [(set (match_dup 2)
-                  (ashift:SI (match_operand:QI 1 "gpc_reg_operand" "")
-                             (const_int 24)))
-   (set (match_operand:HI 0 "gpc_reg_operand" "")
-                  (ashiftrt:SI (match_dup 2)
-                               (const_int 24)))]
-  "! TARGET_POWER"
-  "
-{ operands[0] = gen_lowpart (SImode, operands[0]);
-  operands[1] = gen_lowpart (SImode, operands[1]);
-  operands[2] = gen_reg_rtx (SImode); }")
 \f
 ;; Floating-point insns, excluding normal data motion.
 ;;
   ""
   "
 {
-  if (! TARGET_POWER
+  if (! TARGET_POWER && ! TARGET_POWERPC64
       && short_cint_operand (operands[2], DImode))
     FAIL;
 }")
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
        (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r")
                 (match_operand:DI 2 "reg_or_short_operand" "r,I")))]
-  "TARGET_POWER"
+  "TARGET_POWER && ! TARGET_POWERPC64"
   "@
    {a|addc} %L0,%L1,%L2\;{ae|adde} %0,%1,%2
    {ai|addic} %L0,%L1,%2\;{a%G2e|add%G2e} %0,%1"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
                 (match_operand:DI 2 "gpc_reg_operand" "r")))]
-  "! TARGET_POWER"
+  "! TARGET_POWER && ! TARGET_POWERPC64"
   "addc %L0,%L1,%L2\;adde %0,%1,%2"
   [(set_attr "length" "8")])
 
   ""
   "
 {
-  if (! TARGET_POWER
+  if (! TARGET_POWER && ! TARGET_POWERPC64
       && short_cint_operand (operands[1], DImode))
     FAIL;
 }")
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
        (minus:DI (match_operand:DI 1 "reg_or_short_operand" "r,I")
                  (match_operand:DI 2 "gpc_reg_operand" "r,r")))]
-  "TARGET_POWER"
+  "TARGET_POWER && ! TARGET_POWERPC64"
   "@
    {sf|subfc} %L0,%L2,%L1\;{sfe|subfe} %0,%2,%1
    {sfi|subfic} %L0,%L2,%1\;{sf%G1e|subf%G1e} %0,%2"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (minus:DI (match_operand:DI 1 "gpc_reg_operand" "r")
                  (match_operand:DI 2 "gpc_reg_operand" "r")))]
-  "! TARGET_POWER"
+  "! TARGET_POWER && ! TARGET_POWERPC64"
   "subfc %L0,%L2,%L1\;subfe %0,%2,%1"
   [(set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
-  ""
+  "! TARGET_POWERPC64"
   "{sfi|subfic} %L0,%L1,0\;{sfze|subfze} %0,%1"
   [(set_attr "length" "8")])
 
 ;; just handle shifts by constants.
 
 (define_expand "ashrdi3"
-  [(parallel [(set (match_operand:DI 0 "gpc_reg_operand" "=")
-                  (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                               (match_operand:SI 2 "general_operand" "")))
-             (clobber (match_scratch:SI 3 ""))])]
-  "TARGET_POWER"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+       (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
+                    (match_operand:SI 2 "reg_or_cint_operand" "")))]
+  ""
   "
-{ if (GET_CODE (operands[2]) != CONST_INT)
+{
+  if (TARGET_POWER && GET_CODE (operands[2]) != CONST_INT)
+    {
+      emit_insn (gen_ashrdi3_power (operands[0], operands[1], operands[2]));
+      DONE;
+    }
+  else if (! TARGET_POWERPC64)
     FAIL;
 }")
 
-(define_insn ""
+(define_insn "ashrdi3_power"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
        (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
                     (match_operand:SI 2 "const_int_operand" "M,i")))
 (define_insn ""
   [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,o,!r,f,f,m")
        (match_operand:DF 1 "input_operand" "r,o,r,G,f,m,f"))]
-  "register_operand (operands[0], DFmode)
-   || register_operand (operands[1], DFmode)"
+  "! TARGET_POWERPC64 && (register_operand (operands[0], DFmode)
+   || register_operand (operands[1], DFmode))"
   "*
 {
   switch (which_alternative)
 }"
   [(set_attr "type" "*,load,*,*,fp,fpload,*")
    (set_attr "length" "8,8,8,8,*,*,*")])
+
+(define_insn ""
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,o,!r,f,f,m")
+       (match_operand:DF 1 "input_operand" "r,o,r,G,f,m,f"))]
+  "TARGET_POWERPC64 && (register_operand (operands[0], DFmode)
+   || register_operand (operands[1], DFmode))"
+  "@
+  mr %0,%1
+  ld%U1%X1 %0,%1
+  sd%U0%X0 %1,%0
+  #
+  fmr %0,%1
+  lfd %0,%1
+  stfd%U0%X0 %1,%0"
+  [(set_attr "type" "*,load,*,*,fp,fpload,*")])
 \f
 ;; Next come the multi-word integer load and store and the load and store
 ;; multiple insns.
 (define_insn ""
   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,f,f,m")
        (match_operand:DI 1 "input_operand" "r,m,r,f,m,f"))]
-  "gpc_reg_operand (operands[0], DImode)
-   || gpc_reg_operand (operands[1], DImode)"
+  "! TARGET_POWERPC64 && (gpc_reg_operand (operands[0], DImode)
+   || gpc_reg_operand (operands[1], DImode))"
   "*
 {
   switch (which_alternative)
 }"
   [(set_attr "type" "*,load,*,fp,fpload,*")
    (set_attr "length" "8,8,8,*,*,*")])
+
+(define_insn ""
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,f,f,m,r,*h")
+       (match_operand:DI 1 "input_operand" "r,m,r,I,J,f,m,f,*h,r"))]
+  "TARGET_POWERPC64 && (gpc_reg_operand (operands[0], DImode)
+   || gpc_reg_operand (operands[1], DImode))"
+  "@
+  mr %0,%1
+  ld%U1%X1 %0,%1
+  sd%U0%X0 %1,%0
+  li %0,%1
+  lis %0,%u1
+  fmr %0,%1
+  lfd%U1%X1 %0,%1
+  stfd%U0%X0 %1,%0
+  mf%1 %0
+  mt%0 %1"
+  [(set_attr "type" "*,load,*,*,*,fp,fpload,*,*,mtjmpr")])
 \f
 ;; TImode is similar, except that we usually want to compute the address into
 ;; a register and use lsi/stsi (the exception is during reload).  MQ is also
   [(parallel [(set (match_operand:TI 0 "general_operand" "")
                   (match_operand:TI 1 "general_operand" ""))
              (clobber (scratch:SI))])]
-  "TARGET_POWER"
+  "TARGET_POWER || TARGET_POWERPC64"
   "
 {
   if (GET_CODE (operands[0]) == MEM)
   [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r")
        (match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m"))
    (clobber (match_scratch:SI 2 "=q,q#X,X,X,X"))]
-  "TARGET_POWER && (gpc_reg_operand (operands[0], TImode)
+  "TARGET_POWER && ! TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode)
    || gpc_reg_operand (operands[1], TImode))"
   "*
 {
 }"
   [(set_attr "type" "*,load,load,*,*")
    (set_attr "length" "*,16,16,*,16")])
+
+(define_insn ""
+  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,r,m")
+       (match_operand:TI 1 "input_operand" "r,m,r"))]
+  "TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode)
+   || gpc_reg_operand (operands[1], TImode))"
+  "*
+{
+  switch (which_alternative)
+    {
+    case 0:
+      /* We normally copy the low-numbered register first.  However, if
+        the first register operand 0 is the same as the second register of
+        operand 1, we must copy in the opposite order.  */
+      if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
+       return \"mr %L0,%L1\;mr %0,%1\";
+      else
+       return \"mr %0,%1\;mr %L0,%L1\";
+    case 1:
+      /* If the low-address word is used in the address, we must load it
+        last.  Otherwise, load it first.  Note that we cannot have
+        auto-increment in that case since the address register is known to be
+        dead.  */
+      if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
+                            operands [1], 0))
+       return \"ld %L0,%L1\;ld %0,%1\";
+      else
+       return \"ld%U1 %0,%1\;ld %L0,%L1\";
+    case 2:
+      return \"std%U0 %1,%0\;std %L1,%L0\";
+    }
+}"
+  [(set_attr "type" "*,load,*")
+   (set_attr "length" "8,8,8")])
 \f
 (define_expand "load_multiple"
   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
 ;; tie and these are the pair most likely to be tieable (and the ones
 ;; that will benefit the most).
 
+(define_insn ""
+  [(set (match_operand:DI 3 "gpc_reg_operand" "=r,r")
+       (mem:SI (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0")
+                        (match_operand:DI 2 "reg_or_short_operand" "r,I"))))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
+       (plus:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_POWERPC64"
+  "@
+   ldux %3,%0,%2
+   ldu %3,%2(%0)"
+  [(set_attr "type" "load")])
+
+(define_insn ""
+  [(set (mem:DI (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0")
+                        (match_operand:DI 2 "reg_or_short_operand" "r,I")))
+       (match_operand:DI 3 "gpc_reg_operand" "r,r"))
+   (set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
+       (plus:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_POWERPC64"
+  "@
+   stdux %3,%0,%2
+   stdu %3,%2(%0)")
+
 (define_insn ""
   [(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
        (mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
 }"
   [(set_attr "type" "branch")])
 
-
 (define_insn ""
   [(set (pc)
        (if_then_else (match_operator 0 "branch_comparison_operator"