]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/pa/pa.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / pa / pa.md
index b620193e5462b651acc3431908daf1bb43c59a4a..547a450b20ede8e10933d481fe4f065813f1c0b4 100644 (file)
@@ -1,6 +1,5 @@
 ;;- Machine description for HP PA-RISC architecture for GCC compiler
-;;   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-;;   2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;;   Copyright (C) 1992-2020 Free Software Foundation, Inc.
 ;;   Contributed by the Center for Software Science at the University
 ;;   of Utah.
 
 ;; along with GCC; see the file COPYING3.  If not see
 ;; <http://www.gnu.org/licenses/>.
 
-;; This gcc Version 2 machine description is inspired by sparc.md and
-;; mips.md.
+;; This machine description is inspired by sparc.md and to a lesser
+;; extent mips.md.
+
+;; Possible improvements:
+;;
+;; * With PA1.1, most computational instructions can conditionally nullify
+;;   the execution of the following instruction.  A nullified instruction
+;;   does not cause the instruction pipeline to stall, making it a very
+;;   efficient alternative to e.g. branching or conditional moves.
+;;
+;;   Nullification is performed conditionally based on the outcome of a
+;;   test specified in the opcode.  The test result is stored in PSW[N]
+;;   and can only be used to nullify the instruction following immediately
+;;   after the test.  For example:
+;;
+;;     ldi 10,%r26
+;;     ldi 5,%r25
+;;     sub,< %r26,%r25,%r28
+;;     sub   %r28,%r25,%r28    ; %r28 == 0
+;;     sub,> %r26,%r25,%r29
+;;     sub   %r29,%r25,%r29    ; %r29 == 5
+;;
+;;   This could be tricky to implement because the result of the test has
+;;   to be propagated one instruction forward, which, in the worst case,
+;;   would involve (1) adding a fake register for PSW[N]; (2) adding the
+;;   variants of the computational instructions that set or consume this
+;;   fake register.  The cond_exec infrastructure is probably not helpful
+;;   for this.
+;;
+;; * PA-RISC includes a set of conventions for branch instruction usage
+;;   to indicate whether a particular branch is more likely to be taken
+;;   or not taken.  For example, the prediction for CMPB instructions
+;;   (CMPB,cond,n r1,r2,target) depends on the direction of the branch
+;;   (forward or backward) and on the order of the operands:
+;;
+;;     | branch    | operand  | branch     |
+;;     | direction | compare  | prediction |
+;;     +-----------+----------+------------+
+;;     | backward  | r1 < r2  | taken      |
+;;     | backward  | r1 >= r2 | not taken  |
+;;     | forward   | r1 < r2  | not taken  |
+;;     | forward   | r1 >= r2 | taken      |
+;;    
+;;   By choosing instructions and operand order carefully, the compiler
+;;   could give the CPU branch predictor some help.
+;;   
 
 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
 
 ;; Uses of UNSPEC in this file:
 
-(define_constants
-  [(UNSPEC_CFFC                0)      ; canonicalize_funcptr_for_compare
-   (UNSPEC_GOTO                1)      ; indirect_goto
-   (UNSPEC_DLTIND14R   2)      ; 
-   (UNSPEC_TP          3)
-   (UNSPEC_TLSGD       4)
-   (UNSPEC_TLSLDM      5)
-   (UNSPEC_TLSLDO      6)
-   (UNSPEC_TLSLDBASE   7)
-   (UNSPEC_TLSIE       8)
-   (UNSPEC_TLSLE       9)
-   (UNSPEC_TLSGD_PIC   10)
-   (UNSPEC_TLSLDM_PIC  11)
-   (UNSPEC_TLSIE_PIC   12)
+(define_c_enum "unspec"
+  [UNSPEC_CFFC         ; canonicalize_funcptr_for_compare
+   UNSPEC_GOTO         ; indirect_goto
+   UNSPEC_DLTIND14R
+   UNSPEC_TP
+   UNSPEC_TLSGD
+   UNSPEC_TLSLDM
+   UNSPEC_TLSLDO
+   UNSPEC_TLSLDBASE
+   UNSPEC_TLSIE
+   UNSPEC_TLSLE 
+   UNSPEC_TLSGD_PIC
+   UNSPEC_TLSLDM_PIC
+   UNSPEC_TLSIE_PIC
+   UNSPEC_MEMORY_BARRIER
   ])
 
 ;; UNSPEC_VOLATILE:
 
-(define_constants
-  [(UNSPECV_BLOCKAGE   0)      ; blockage
-   (UNSPECV_DCACHE     1)      ; dcacheflush
-   (UNSPECV_ICACHE     2)      ; icacheflush
-   (UNSPECV_OPC                3)      ; outline_prologue_call
-   (UNSPECV_OEC                4)      ; outline_epilogue_call
-   (UNSPECV_LONGJMP    5)      ; builtin_longjmp
+(define_c_enum "unspecv"
+  [UNSPECV_BLOCKAGE    ; blockage
+   UNSPECV_DCACHE      ; dcacheflush
+   UNSPECV_ICACHE      ; icacheflush
+   UNSPECV_OPC         ; outline_prologue_call
+   UNSPECV_OEC         ; outline_epilogue_call
+   UNSPECV_LONGJMP     ; builtin_longjmp
   ])
 
 ;; Maximum pc-relative branch offsets.
 ;; type "binary" insns have two input operands (1,2) and one output (0)
 
 (define_attr "type"
-  "move,unary,binary,shift,nullshift,compare,load,store,uncond_branch,btable_branch,branch,cbranch,fbranch,call,dyncall,fpload,fpstore,fpalu,fpcc,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,multi,milli,parallel_branch,fpstore_load,store_fpload"
+  "move,unary,binary,shift,nullshift,compare,load,store,uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,fpload,fpstore,fpalu,fpcc,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,multi,milli,sh_func_adrs,parallel_branch,fpstore_load,store_fpload,trap"
   (const_string "binary"))
 
 (define_attr "pa_combine_type"
                       (const_int 8) (const_int 4))
 
         (eq_attr "type" "binary,shift,nullshift")
-        (if_then_else (match_operand 2 "arith_operand" "")
+        (if_then_else (match_operand 2 "arith14_operand" "")
                       (const_int 4) (const_int 12))
 
         (eq_attr "type" "move,unary,shift,nullshift")
-        (if_then_else (match_operand 1 "arith_operand" "")
+        (if_then_else (match_operand 1 "arith14_operand" "")
                       (const_int 4) (const_int 8))]
 
        (const_int 4)))
 
 ;; Attributes for instruction and branch scheduling
 
-;; For conditional branches.
+;; For conditional branches. Frame related instructions are not allowed
+;; because they confuse the unwind support.
 (define_attr "in_branch_delay" "false,true"
-  (if_then_else (and (eq_attr "type" "!uncond_branch,btable_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,parallel_branch")
-                    (eq_attr "length" "4"))
+  (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,multi,milli,sh_func_adrs,parallel_branch,trap")
+                    (eq_attr "length" "4")
+                    (not (match_test "RTX_FRAME_RELATED_P (insn)")))
                (const_string "true")
                (const_string "false")))
 
 ;; Disallow instructions which use the FPU since they will tie up the FPU
 ;; even if the instruction is nullified.
 (define_attr "in_nullified_branch_delay" "false,true"
-  (if_then_else (and (eq_attr "type" "!uncond_branch,btable_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,parallel_branch")
-                    (eq_attr "length" "4"))
+  (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,multi,milli,sh_func_adrs,fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,parallel_branch,trap")
+                    (eq_attr "length" "4")
+                    (not (match_test "RTX_FRAME_RELATED_P (insn)")))
                (const_string "true")
                (const_string "false")))
 
-;; For calls and millicode calls.  Allow unconditional branches in the
-;; delay slot.
+;; For calls and millicode calls.
 (define_attr "in_call_delay" "false,true"
-  (cond [(and (eq_attr "type" "!uncond_branch,btable_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,parallel_branch")
-             (eq_attr "length" "4"))
-          (const_string "true")
-        (eq_attr "type" "uncond_branch")
-          (if_then_else (ne (symbol_ref "TARGET_JUMP_IN_DELAY")
-                            (const_int 0))
-                        (const_string "true")
-                        (const_string "false"))]
-       (const_string "false")))
-
+  (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,multi,milli,sh_func_adrs,parallel_branch,trap")
+                    (eq_attr "length" "4")
+                    (not (match_test "RTX_FRAME_RELATED_P (insn)")))
+               (const_string "true")
+               (const_string "false")))
 
 ;; Call delay slot description.
 (define_delay (eq_attr "type" "call")
   [(eq_attr "in_call_delay" "true") (nil) (nil)])
 
+;; Sibcall delay slot description.
+(define_delay (eq_attr "type" "sibcall")
+  [(eq_attr "in_call_delay" "true") (nil) (nil)])
+
 ;; Millicode call delay slot description.
 (define_delay (eq_attr "type" "milli")
   [(eq_attr "in_call_delay" "true") (nil) (nil)])
 
 ;; Return and other similar instructions.
-(define_delay (eq_attr "type" "btable_branch,branch,parallel_branch")
+(define_delay (eq_attr "type" "branch,parallel_branch")
   [(eq_attr "in_branch_delay" "true") (nil) (nil)])
 
 ;; Floating point conditional branch delay slot description.
    (and (eq_attr "in_nullified_branch_delay" "true")
        (attr_flag "backward"))])
 
-(define_delay (and (eq_attr "type" "uncond_branch")
-                  (eq (symbol_ref "following_call (insn)")
-                      (const_int 0)))
+(define_delay (eq_attr "type" "uncond_branch")
   [(eq_attr "in_branch_delay" "true") (nil) (nil)])
 
 ;; Memory. Disregarding Cache misses, the Mustang memory times are:
 
 ;; We have a bypass for all computations in the FP unit which feed an
 ;; FP store as long as the sizes are the same.
-(define_bypass 2 "W1,W2" "W10,W11" "hppa_fpstore_bypass_p")
-(define_bypass 9 "W3" "W10,W11" "hppa_fpstore_bypass_p")
-(define_bypass 11 "W4" "W10,W11" "hppa_fpstore_bypass_p")
-(define_bypass 13 "W5" "W10,W11" "hppa_fpstore_bypass_p")
-(define_bypass 17 "W6" "W10,W11" "hppa_fpstore_bypass_p")
+(define_bypass 2 "W1,W2" "W10,W11" "pa_fpstore_bypass_p")
+(define_bypass 9 "W3" "W10,W11" "pa_fpstore_bypass_p")
+(define_bypass 11 "W4" "W10,W11" "pa_fpstore_bypass_p")
+(define_bypass 13 "W5" "W10,W11" "pa_fpstore_bypass_p")
+(define_bypass 17 "W6" "W10,W11" "pa_fpstore_bypass_p")
 
 ;; We have an "anti-bypass" for FP loads which feed an FP store.
-(define_bypass 4 "W8,W12" "W10,W11" "hppa_fpstore_bypass_p")
+(define_bypass 4 "W8,W12" "W10,W11" "pa_fpstore_bypass_p")
 
 ;; Function units for the 7100 and 7150.  The 7100/7150 can dual-issue
 ;; floating point computations with non-floating point computations (fp loads
 
 ;; We have a bypass for all computations in the FP unit which feed an
 ;; FP store as long as the sizes are the same.
-(define_bypass 1 "X0" "X6,X7" "hppa_fpstore_bypass_p")
-(define_bypass 7 "X1" "X6,X7" "hppa_fpstore_bypass_p")
-(define_bypass 14 "X2" "X6,X7" "hppa_fpstore_bypass_p")
+(define_bypass 1 "X0" "X6,X7" "pa_fpstore_bypass_p")
+(define_bypass 7 "X1" "X6,X7" "pa_fpstore_bypass_p")
+(define_bypass 14 "X2" "X6,X7" "pa_fpstore_bypass_p")
 
 ;; We have an "anti-bypass" for FP loads which feed an FP store.
-(define_bypass 3 "X4,X8" "X6,X7" "hppa_fpstore_bypass_p")
+(define_bypass 3 "X4,X8" "X6,X7" "pa_fpstore_bypass_p")
 
 ;; The 7100LC has three floating-point units: ALU, MUL, and DIV.
 ;; There's no value in modeling the ALU and MUL separately though
   "i1_7100lc,i1_7100lc+mem_7100lc")
 
 ;; We have an "anti-bypass" for FP loads which feed an FP store.
-(define_bypass 3 "Y3,Y7,Y13,Y17" "Y5,Y6,Y11,Y12,Y15,Y16" "hppa_fpstore_bypass_p")
+(define_bypass 3 "Y3,Y7,Y13,Y17" "Y5,Y6,Y11,Y12,Y15,Y16" "pa_fpstore_bypass_p")
 
 ;; Scheduling for the PA8000 is somewhat different than scheduling for a
 ;; traditional architecture.
 ;; to assume have zero latency.
 (define_insn_reservation "Z3" 0
   (and
-    (eq_attr "type" "!load,fpload,store,fpstore,uncond_branch,btable_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,parallel_branch,fpcc,fpalu,fpmulsgl,fpmuldbl,fpsqrtsgl,fpsqrtdbl,fpdivsgl,fpdivdbl,fpstore_load,store_fpload")
+    (eq_attr "type" "!load,fpload,store,fpstore,uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,multi,milli,sh_func_adrs,parallel_branch,fpcc,fpalu,fpmulsgl,fpmuldbl,fpsqrtsgl,fpsqrtdbl,fpdivsgl,fpdivdbl,fpstore_load,store_fpload")
     (eq_attr "cpu" "8000"))
   "inm_8000,rnm_8000")
 
 ;; retirement unit.
 (define_insn_reservation "Z4" 0
   (and
-    (eq_attr "type" "uncond_branch,btable_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,parallel_branch")
+    (eq_attr "type" "uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,multi,milli,sh_func_adrs,parallel_branch")
     (eq_attr "cpu" "8000"))
   "inm0_8000+inm1_8000,rnm0_8000+rnm1_8000")
 
 (define_insn "scc"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (match_operator:SI 3 "comparison_operator"
-                          [(match_operand:SI 1 "register_operand" "r")
+                          [(match_operand:SI 1 "reg_or_0_operand" "rM")
                            (match_operand:SI 2 "arith11_operand" "rI")]))]
   ""
-  "{com%I2clr|cmp%I2clr},%B3 %2,%1,%0\;ldi 1,%0"
+  "{com%I2clr|cmp%I2clr},%B3 %2,%r1,%0\;ldi 1,%0"
   [(set_attr "type" "binary")
    (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
        (match_operator:DI 3 "comparison_operator"
-                          [(match_operand:DI 1 "register_operand" "r")
+                          [(match_operand:DI 1 "reg_or_0_operand" "rM")
                            (match_operand:DI 2 "arith11_operand" "rI")]))]
   "TARGET_64BIT"
-  "cmp%I2clr,*%B3 %2,%1,%0\;ldi 1,%0"
+  "cmp%I2clr,*%B3 %2,%r1,%0\;ldi 1,%0"
   [(set_attr "type" "binary")
    (set_attr "length" "8")])
 
 (define_insn "iorscc"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (ior:SI (match_operator:SI 3 "comparison_operator"
-                                  [(match_operand:SI 1 "register_operand" "r")
+                                  [(match_operand:SI 1 "reg_or_0_operand" "rM")
                                    (match_operand:SI 2 "arith11_operand" "rI")])
                (match_operator:SI 6 "comparison_operator"
-                                  [(match_operand:SI 4 "register_operand" "r")
+                                  [(match_operand:SI 4 "reg_or_0_operand" "rM")
                                    (match_operand:SI 5 "arith11_operand" "rI")])))]
   ""
-  "{com%I2clr|cmp%I2clr},%S3 %2,%1,%%r0\;{com%I5clr|cmp%I5clr},%B6 %5,%4,%0\;ldi 1,%0"
+  "{com%I2clr|cmp%I2clr},%S3 %2,%r1,%%r0\;{com%I5clr|cmp%I5clr},%B6 %5,%r4,%0\;ldi 1,%0"
   [(set_attr "type" "binary")
    (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
        (ior:DI (match_operator:DI 3 "comparison_operator"
-                                  [(match_operand:DI 1 "register_operand" "r")
+                                  [(match_operand:DI 1 "reg_or_0_operand" "rM")
                                    (match_operand:DI 2 "arith11_operand" "rI")])
                (match_operator:DI 6 "comparison_operator"
-                                  [(match_operand:DI 4 "register_operand" "r")
+                                  [(match_operand:DI 4 "reg_or_0_operand" "rM")
                                    (match_operand:DI 5 "arith11_operand" "rI")])))]
   "TARGET_64BIT"
-  "cmp%I2clr,*%S3 %2,%1,%%r0\;cmp%I5clr,*%B6 %5,%4,%0\;ldi 1,%0"
+  "cmp%I2clr,*%S3 %2,%r1,%%r0\;cmp%I5clr,*%B6 %5,%r4,%0\;ldi 1,%0"
   [(set_attr "type" "binary")
    (set_attr "length" "12")])
 
 (define_insn "negscc"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (neg:SI (match_operator:SI 3 "comparison_operator"
-              [(match_operand:SI 1 "register_operand" "r")
+              [(match_operand:SI 1 "reg_or_0_operand" "rM")
                (match_operand:SI 2 "arith11_operand" "rI")])))]
   ""
-  "{com%I2clr|cmp%I2clr},%B3 %2,%1,%0\;ldi -1,%0"
+  "{com%I2clr|cmp%I2clr},%B3 %2,%r1,%0\;ldi -1,%0"
   [(set_attr "type" "binary")
    (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
        (neg:DI (match_operator:DI 3 "comparison_operator"
-              [(match_operand:DI 1 "register_operand" "r")
+              [(match_operand:DI 1 "reg_or_0_operand" "rM")
                (match_operand:DI 2 "arith11_operand" "rI")])))]
   "TARGET_64BIT"
-  "cmp%I2clr,*%B3 %2,%1,%0\;ldi -1,%0"
+  "cmp%I2clr,*%B3 %2,%r1,%0\;ldi -1,%0"
   [(set_attr "type" "binary")
    (set_attr "length" "8")])
 
 [(set_attr "type" "multi,multi")
  (set_attr "length" "8,8")])
 
+(define_insn "absqi2"
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (abs:QI (match_operand:QI 1 "register_operand" "r")))]
+  ""
+  "{extrs|extrw,s},>= %1,31,8,%0\;subi 0,%0,%0"
+  [(set_attr "type" "multi")
+   (set_attr "length" "8")])
+
+(define_insn "abshi2"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (abs:HI (match_operand:HI 1 "register_operand" "r")))]
+  ""
+  "{extrs|extrw,s},>= %1,31,16,%0\;subi 0,%0,%0"
+  [(set_attr "type" "multi")
+   (set_attr "length" "8")])
+
 (define_insn "abssi2"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (abs:SI (match_operand:SI 1 "register_operand" "r")))]
   [(set_attr "type" "multi")
    (set_attr "length" "8")])
 
+(define_insn "bswaphi2"
+  [(set (match_operand:HI 0 "register_operand" "=&r")
+       (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
+  ""
+  "{extru|extrw,u} %1,23,8,%0\;{dep|depw} %1,23,8,%0"
+  [(set_attr "type" "multi")
+   (set_attr "length" "8")])
+
+(define_insn "bswapsi2"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+       (bswap:SI (match_operand:SI 1 "register_operand" "r")))]
+  ""
+  "{shd|shrpw} %1,%1,16,%0\;{dep|depw} %0,15,8,%0\;{shd|shrpw} %1,%0,8,%0"
+  [(set_attr "type" "multi")
+   (set_attr "length" "12")])
+
+(define_insn "bswapdi2"
+  [(set (match_operand:DI 0 "register_operand" "=&r")
+       (bswap:DI (match_operand:DI 1 "register_operand" "r")))
+   (clobber (match_scratch:DI 2 "=r"))]
+  "TARGET_64BIT"
+  "permh,3210 %1,%2\;hshl %2,8,%0\;hshr,u %2,8,%2\;or %0,%2,%0"
+  [(set_attr "type" "multi")
+   (set_attr "length" "16")])
+
 ;;; Experimental conditional move patterns
 
 (define_expand "movsicc"
   ""
   "
 {
-  emit_bcond_fp (operands);
+  pa_emit_bcond_fp (operands);
   DONE;
 }")
 
   ""
   "
 {
-  emit_bcond_fp (operands);
+  pa_emit_bcond_fp (operands);
   DONE;
 }")
 
   ""
   "*
 {
-  return output_cbranch (operands, 0, insn);
+  return pa_output_cbranch (operands, 0, insn);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   ""
   "*
 {
-  return output_cbranch (operands, 1, insn);
+  return pa_output_cbranch (operands, 1, insn);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   "TARGET_64BIT"
   "*
 {
-  return output_cbranch (operands, 0, insn);
+  return pa_output_cbranch (operands, 0, insn);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   "TARGET_64BIT"
   "*
 {
-  return output_cbranch (operands, 1, insn);
+  return pa_output_cbranch (operands, 1, insn);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 (define_insn ""
   "TARGET_64BIT"
   "*
 {
-  return output_cbranch (operands, 0, insn);
+  return pa_output_cbranch (operands, 0, insn);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   "TARGET_64BIT"
   "*
 {
-  return output_cbranch (operands, 1, insn);
+  return pa_output_cbranch (operands, 1, insn);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   ""
   "*
 {
-  return output_bb (operands, 0, insn, 0);
+  return pa_output_bb (operands, 0, insn, 0);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   "TARGET_64BIT"
   "*
 {
-  return output_bb (operands, 0, insn, 0);
+  return pa_output_bb (operands, 0, insn, 0);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   ""
   "*
 {
-  return output_bb (operands, 1, insn, 0);
+  return pa_output_bb (operands, 1, insn, 0);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   "TARGET_64BIT"
   "*
 {
-  return output_bb (operands, 1, insn, 0);
+  return pa_output_bb (operands, 1, insn, 0);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   ""
   "*
 {
-  return output_bb (operands, 0, insn, 1);
+  return pa_output_bb (operands, 0, insn, 1);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   "TARGET_64BIT"
   "*
 {
-  return output_bb (operands, 0, insn, 1);
+  return pa_output_bb (operands, 0, insn, 1);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   ""
   "*
 {
-  return output_bb (operands, 1, insn, 1);
+  return pa_output_bb (operands, 1, insn, 1);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   "TARGET_64BIT"
   "*
 {
-  return output_bb (operands, 1, insn, 1);
+  return pa_output_bb (operands, 1, insn, 1);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   ""
   "*
 {
-  return output_bvb (operands, 0, insn, 0);
+  return pa_output_bvb (operands, 0, insn, 0);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   "TARGET_64BIT"
   "*
 {
-  return output_bvb (operands, 0, insn, 0);
+  return pa_output_bvb (operands, 0, insn, 0);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   ""
   "*
 {
-  return output_bvb (operands, 1, insn, 0);
+  return pa_output_bvb (operands, 1, insn, 0);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   "TARGET_64BIT"
   "*
 {
-  return output_bvb (operands, 1, insn, 0);
+  return pa_output_bvb (operands, 1, insn, 0);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   ""
   "*
 {
-  return output_bvb (operands, 0, insn, 1);
+  return pa_output_bvb (operands, 0, insn, 1);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   "TARGET_64BIT"
   "*
 {
-  return output_bvb (operands, 0, insn, 1);
+  return pa_output_bvb (operands, 0, insn, 1);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   ""
   "*
 {
-  return output_bvb (operands, 1, insn, 1);
+  return pa_output_bvb (operands, 1, insn, 1);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
   "TARGET_64BIT"
   "*
 {
-  return output_bvb (operands, 1, insn, 1);
+  return pa_output_bvb (operands, 1, insn, 1);
 }"
 [(set_attr "type" "cbranch")
  (set (attr "length")
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
     output_asm_insn (\"ftest\;add,tr %%r0,%%r0,%%r0\;b,n .+%0\", xoperands);
   else
     output_asm_insn (\"ftest\;add,tr %%r0,%%r0,%%r0\;b .+%0\", xoperands);
-  return output_lbranch (operands[0], insn, xdelay);
+  return pa_output_lbranch (operands[0], insn, xdelay);
 }"
 [(set_attr "type" "fbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 32)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 28)]
          (const_int 36)))])
 
     output_asm_insn (\"ftest\;b,n .+%0\", xoperands);
   else
     output_asm_insn (\"ftest\;b .+%0\", xoperands);
-  return output_lbranch (operands[0], insn, xdelay);
+  return pa_output_lbranch (operands[0], insn, xdelay);
 }"
 [(set_attr "type" "fbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 12)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 28)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 24)]
          (const_int 32)))])
 
   ""
   "
 {
-  if (emit_move_sequence (operands, SImode, 0))
+  if (pa_emit_move_sequence (operands, SImode, 0))
     DONE;
 }")
 
   ""
   "
 {
-  if (emit_move_sequence (operands, SImode, operands[2]))
+  if (pa_emit_move_sequence (operands, SImode, operands[2]))
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves.  */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 }")
 
   ""
   "
 {
-  if (emit_move_sequence (operands, SImode, operands[2]))
+  if (pa_emit_move_sequence (operands, SImode, operands[2]))
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves.  */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 }")
 
   ""
   "
 {
-  if (emit_move_sequence (operands, SImode, operands[2]))
+  if (pa_emit_move_sequence (operands, SImode, operands[2]))
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves.  */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 }")
 
 ; computes the address to be deleted if the register it sets is dead.
 (define_peephole2
   [(set (match_operand:SI 0 "register_operand" "")
-       (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "")
-                         (const_int 4))
+       (plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
+                           (const_int 2))
                 (match_operand:SI 2 "register_operand" "")))
    (set (mem:SI (match_dup 0))
         (match_operand:SI 3 "register_operand" ""))]
    && FP_REGNO_P (REGNO (operands[3]))"
   [(set (mem:SI (plus:SI (mult:SI (match_dup 1) (const_int 4)) (match_dup 2)))
        (match_dup 3))
-   (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 4))
-                              (match_dup 2)))]
-  "")
-
-(define_peephole2
-  [(set (match_operand:SI 0 "register_operand" "")
-       (plus:SI (match_operand:SI 2 "register_operand" "")
-                (mult:SI (match_operand:SI 1 "register_operand" "")
-                         (const_int 4))))
-   (set (mem:SI (match_dup 0))
-        (match_operand:SI 3 "register_operand" ""))]
-  "!TARGET_SOFT_FLOAT
-   && !TARGET_DISABLE_INDEXING
-   && REG_OK_FOR_BASE_P (operands[2])
-   && FP_REGNO_P (REGNO (operands[3]))"
-  [(set (mem:SI (plus:SI (mult:SI (match_dup 1) (const_int 4)) (match_dup 2)))
-       (match_dup 3))
-   (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 4))
+   (set (match_dup 0) (plus:SI (ashift:SI (match_dup 1) (const_int 2))
                               (match_dup 2)))]
   "")
 
 (define_peephole2
   [(set (match_operand:DI 0 "register_operand" "")
-       (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "")
-                         (const_int 4))
+       (plus:DI (ashift:DI (match_operand:DI 1 "register_operand" "")
+                           (const_int 2))
                 (match_operand:DI 2 "register_operand" "")))
    (set (mem:SI (match_dup 0))
         (match_operand:SI 3 "register_operand" ""))]
    && FP_REGNO_P (REGNO (operands[3]))"
   [(set (mem:SI (plus:DI (mult:DI (match_dup 1) (const_int 4)) (match_dup 2)))
        (match_dup 3))
-   (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 4))
-                              (match_dup 2)))]
-  "")
-
-(define_peephole2
-  [(set (match_operand:DI 0 "register_operand" "")
-       (plus:DI (match_operand:DI 2 "register_operand" "")
-                (mult:DI (match_operand:DI 1 "register_operand" "")
-                         (const_int 4))))
-   (set (mem:SI (match_dup 0))
-        (match_operand:SI 3 "register_operand" ""))]
-  "!TARGET_SOFT_FLOAT
-   && !TARGET_DISABLE_INDEXING
-   && TARGET_64BIT
-   && REG_OK_FOR_BASE_P (operands[2])
-   && FP_REGNO_P (REGNO (operands[3]))"
-  [(set (mem:SI (plus:DI (mult:DI (match_dup 1) (const_int 4)) (match_dup 2)))
-       (match_dup 3))
-   (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 4))
+   (set (match_dup 0) (plus:DI (ashift:DI (match_dup 1) (const_int 2))
                               (match_dup 2)))]
   "")
 
 
   xoperands[0] = operands[0];
   xoperands[1] = operands[1];
-  xoperands[2] = gen_label_rtx ();
-
-  (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
-                                    CODE_LABEL_NUMBER (xoperands[2]));
-  output_asm_insn (\"mfia %0\", xoperands);
 
-  /* If we're trying to load the address of a label that happens to be
-     close, then we can use a shorter sequence.  */
   if (GET_CODE (operands[1]) == LABEL_REF
-      && !LABEL_REF_NONLOCAL_P (operands[1])
-      && INSN_ADDRESSES_SET_P ()
-      && abs (INSN_ADDRESSES (INSN_UID (XEXP (operands[1], 0)))
-               - INSN_ADDRESSES (INSN_UID (insn))) < 8100)
-    output_asm_insn (\"ldo %1-%2(%0),%0\", xoperands);
+      && !LABEL_REF_NONLOCAL_P (operands[1]))
+    {
+      xoperands[2] = gen_label_rtx ();
+      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
+                                        CODE_LABEL_NUMBER (xoperands[2]));
+      output_asm_insn (\"mfia %0\", xoperands);
+
+      /* If we're trying to load the address of a label that happens to be
+        close, then we can use a shorter sequence.  */
+      if (INSN_ADDRESSES_SET_P ()
+         && abs (INSN_ADDRESSES (INSN_UID (XEXP (operands[1], 0)))
+                 - INSN_ADDRESSES (INSN_UID (insn))) < 8100)
+       output_asm_insn (\"ldo %1-%2(%0),%0\", xoperands);
+      else
+       {
+         output_asm_insn (\"addil L%%%1-%2,%0\", xoperands);
+         output_asm_insn (\"ldo R%%%1-%2(%0),%0\", xoperands);
+       }
+    }
   else
     {
-      output_asm_insn (\"addil L%%%1-%2,%0\", xoperands);
-      output_asm_insn (\"ldo R%%%1-%2(%0),%0\", xoperands);
+      /* Load using linkage table.  */
+      if (TARGET_64BIT)
+       {
+         output_asm_insn (\"addil LT%%%1,%%r27\", xoperands);
+         output_asm_insn (\"ldd RT%%%1(%0),%0\", xoperands);
+       }
+      else
+       {
+         output_asm_insn (\"addil LT%%%1,%%r19\", xoperands);
+         output_asm_insn (\"ldw RT%%%1(%0),%0\", xoperands);
+       }
     }
   return \"\";
 }"
 
   xoperands[0] = operands[0];
   xoperands[1] = operands[1];
-  xoperands[2] = gen_label_rtx ();
-
-  output_asm_insn (\"bl .+8,%0\", xoperands);
-  output_asm_insn (\"depi 0,31,2,%0\", xoperands);
-  (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
-                                    CODE_LABEL_NUMBER (xoperands[2]));
 
-  /* If we're trying to load the address of a label that happens to be
-     close, then we can use a shorter sequence.  */
   if (GET_CODE (operands[1]) == LABEL_REF
-      && !LABEL_REF_NONLOCAL_P (operands[1])
-      && INSN_ADDRESSES_SET_P ()
-      && abs (INSN_ADDRESSES (INSN_UID (XEXP (operands[1], 0)))
-               - INSN_ADDRESSES (INSN_UID (insn))) < 8100)
-    output_asm_insn (\"ldo %1-%2(%0),%0\", xoperands);
+      && !LABEL_REF_NONLOCAL_P (operands[1]))
+    {
+      xoperands[2] = gen_label_rtx ();
+      output_asm_insn (\"bl .+8,%0\", xoperands);
+      output_asm_insn (\"depi 0,31,2,%0\", xoperands);
+      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
+                                        CODE_LABEL_NUMBER (xoperands[2]));
+
+      /* If we're trying to load the address of a label that happens to be
+        close, then we can use a shorter sequence.  */
+      if (INSN_ADDRESSES_SET_P ()
+         && abs (INSN_ADDRESSES (INSN_UID (XEXP (operands[1], 0)))
+                 - INSN_ADDRESSES (INSN_UID (insn))) < 8100)
+       output_asm_insn (\"ldo %1-%2(%0),%0\", xoperands);
+      else
+       {
+         output_asm_insn (\"addil L%%%1-%2,%0\", xoperands);
+         output_asm_insn (\"ldo R%%%1-%2(%0),%0\", xoperands);
+       }
+    }
   else
     {
-      output_asm_insn (\"addil L%%%1-%2,%0\", xoperands);
-      output_asm_insn (\"ldo R%%%1-%2(%0),%0\", xoperands);
+      /* Load using linkage table.  */
+      output_asm_insn (\"addil LT%%%1,%%r19\", xoperands);
+      output_asm_insn (\"ldw RT%%%1(%0),%0\", xoperands);
     }
   return \"\";
 }"
   [(set_attr "type" "binary")
    (set_attr "length" "4")])
 
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+       (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+                 (unspec:SI [(match_operand 2 "" "")] UNSPEC_DLTIND14R)))]
+  "symbolic_operand (operands[2], Pmode)
+   && ! function_label_operand (operands[2], Pmode)
+   && flag_pic"
+  "ldo RT'%G2(%1),%0"
+  [(set_attr "type" "binary")
+   (set_attr "length" "4")])
+
+(define_insn ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
+       (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+                 (unspec:DI [(match_operand 2 "" "")] UNSPEC_DLTIND14R)))]
+  "symbolic_operand (operands[2], Pmode)
+   && ! function_label_operand (operands[2], Pmode)
+   && TARGET_64BIT
+   && flag_pic"
+  "ldo RT'%G2(%1),%0"
+  [(set_attr "type" "binary")
+   (set_attr "length" "4")])
+
 ;; Always use addil rather than ldil;add sequences.  This allows the
 ;; HP linker to eliminate the dp relocation if the symbolic operand
 ;; lives in the TEXT space.
 }"
   [(set_attr "type" "binary")
    (set (attr "length")
-      (if_then_else (eq (symbol_ref "TARGET_LONG_LOAD_STORE") (const_int 0))
+      (if_then_else (not (match_test "TARGET_LONG_LOAD_STORE"))
                    (const_int 4)
                    (const_int 8)))])
 
   [(set (match_operand:SI 0 "register_operand" "=r")
        (high:SI (match_operand 1 "" "")))]
   "(!flag_pic || !symbolic_operand (operands[1], Pmode))
-    && !is_function_label_plus_const (operands[1])"
+    && !pa_is_function_label_plus_const (operands[1])"
   "*
 {
   if (symbolic_operand (operands[1], Pmode))
   [(set (match_operand:SI 0 "register_operand" "=r")
        (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
                   (match_operand:SI 2 "immediate_operand" "i")))]
-  "!is_function_label_plus_const (operands[2])"
+  "!pa_is_function_label_plus_const (operands[2])"
   "*
 {
   gcc_assert (!flag_pic || !symbolic_operand (operands[2], Pmode));
 ;; a 2 insn store with some creative RTL rewriting.
 (define_split
   [(set (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "")
-                              (match_operand:SI 1 "shadd_operand" ""))
+                              (match_operand:SI 1 "mem_shadd_operand" ""))
                   (plus:SI (match_operand:SI 2 "register_operand" "")
                            (match_operand:SI 3 "const_int_operand" ""))))
        (match_operand:SI 4 "register_operand" ""))
    (clobber (match_operand:SI 5 "register_operand" ""))]
   ""
-  [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
+  [(set (match_dup 5) (plus:SI (ashift:SI (match_dup 0) (match_dup 1))
                               (match_dup 2)))
    (set (mem:SI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))]
-  "")
+  "
+{
+  operands[1] = GEN_INT (exact_log2 (INTVAL (operands[1])));
+
+}")
 
 (define_split
   [(set (mem:HI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "")
-                              (match_operand:SI 1 "shadd_operand" ""))
+                              (match_operand:SI 1 "mem_shadd_operand" ""))
                   (plus:SI (match_operand:SI 2 "register_operand" "")
                            (match_operand:SI 3 "const_int_operand" ""))))
        (match_operand:HI 4 "register_operand" ""))
    (clobber (match_operand:SI 5 "register_operand" ""))]
   ""
-  [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
+  [(set (match_dup 5) (plus:SI (ashift:SI (match_dup 0) (match_dup 1))
                               (match_dup 2)))
    (set (mem:HI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))]
-  "")
+  "
+{
+  operands[1] = GEN_INT (exact_log2 (INTVAL (operands[1])));
+
+}")
 
 (define_split
   [(set (mem:QI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "")
-                              (match_operand:SI 1 "shadd_operand" ""))
+                              (match_operand:SI 1 "mem_shadd_operand" ""))
                   (plus:SI (match_operand:SI 2 "register_operand" "")
                            (match_operand:SI 3 "const_int_operand" ""))))
        (match_operand:QI 4 "register_operand" ""))
    (clobber (match_operand:SI 5 "register_operand" ""))]
   ""
-  [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
+  [(set (match_dup 5) (plus:SI (ashift:SI (match_dup 0) (match_dup 1))
                               (match_dup 2)))
    (set (mem:QI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))]
-  "")
+  "
+{
+  operands[1] = GEN_INT (exact_log2 (INTVAL (operands[1])));
+
+}")
 
 (define_expand "movhi"
   [(set (match_operand:HI 0 "general_operand" "")
   ""
   "
 {
-  if (emit_move_sequence (operands, HImode, 0))
+  if (pa_emit_move_sequence (operands, HImode, 0))
     DONE;
 }")
 
   ""
   "
 {
-  if (emit_move_sequence (operands, HImode, operands[2]))
+  if (pa_emit_move_sequence (operands, HImode, operands[2]))
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves.  */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 }")
 
   ""
   "
 {
-  if (emit_move_sequence (operands, HImode, operands[2]))
+  if (pa_emit_move_sequence (operands, HImode, operands[2]))
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves.  */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 }")
 
   [(set_attr "type" "store")
    (set_attr "length" "4")])
 
-(define_insn ""
-  [(set (match_operand:HI 0 "register_operand" "=r")
-       (plus:HI (match_operand:HI 1 "register_operand" "r")
-                (match_operand 2 "const_int_operand" "J")))]
+(define_insn "addhi3"
+  [(set (match_operand:HI 0 "register_operand" "=r,r")
+       (plus:HI (match_operand:HI 1 "register_operand" "%r,r")
+                (match_operand:HI 2 "arith14_operand" "r,J")))]
   ""
-  "ldo %2(%1),%0"
-  [(set_attr "type" "binary")
+  "@
+   {addl|add,l} %1,%2,%0
+   ldo %2(%1),%0"
+  [(set_attr "type" "binary,binary")
    (set_attr "pa_combine_type" "addmove")
-   (set_attr "length" "4")])
+   (set_attr "length" "4,4")])
 
 (define_expand "movqi"
   [(set (match_operand:QI 0 "general_operand" "")
   ""
   "
 {
-  if (emit_move_sequence (operands, QImode, 0))
+  if (pa_emit_move_sequence (operands, QImode, 0))
     DONE;
 }")
 
   ""
   "
 {
-  if (emit_move_sequence (operands, QImode, operands[2]))
+  if (pa_emit_move_sequence (operands, QImode, operands[2]))
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves.  */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 }")
 
   ""
   "
 {
-  if (emit_move_sequence (operands, QImode, operands[2]))
+  if (pa_emit_move_sequence (operands, QImode, operands[2]))
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves.  */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 }")
 
 
 ;; The definition of this insn does not really explain what it does,
 ;; but it should suffice that anything generated as this insn will be
-;; recognized as a movmemsi operation, and that it will not successfully
+;; recognized as a cpymemsi operation, and that it will not successfully
 ;; combine with anything.
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
   [(parallel [(set (match_operand:BLK 0 "" "")
                   (match_operand:BLK 1 "" ""))
              (clobber (match_dup 4))
              (clobber (match_dup 6))
              (clobber (match_dup 7))
              (clobber (match_dup 8))
-             (use (match_operand:SI 2 "arith_operand" ""))
+             (use (match_operand:SI 2 "arith14_operand" ""))
              (use (match_operand:SI 3 "const_int_operand" ""))])]
   "!TARGET_64BIT && optimize > 0"
   "
 }")
 
 ;; The operand constraints are written like this to support both compile-time
-;; and run-time determined byte counts.  The expander and output_block_move
+;; and run-time determined byte counts.  The expander and pa_output_block_move
 ;; only support compile-time determined counts at this time.
 ;;
 ;; If the count is run-time determined, the register with the byte count
 ;; operands 0 and 1 are both equivalent to symbolic MEMs.  Thus, we are
 ;; forced to internally copy operands 0 and 1 to operands 7 and 8,
 ;; respectively.  We then split or peephole optimize after reload.
-(define_insn "movmemsi_prereload"
+(define_insn "cpymemsi_prereload"
   [(set (mem:BLK (match_operand:SI 0 "register_operand" "r,r"))
        (mem:BLK (match_operand:SI 1 "register_operand" "r,r")))
    (clobber (match_operand:SI 2 "register_operand" "=&r,&r"))  ;loop cnt/tmp
    (clobber (match_operand:SI 6 "register_operand" "=&r,&r"))  ;item tmp2
    (clobber (match_operand:SI 7 "register_operand" "=&r,&r"))  ;item tmp3
    (clobber (match_operand:SI 8 "register_operand" "=&r,&r"))  ;item tmp4
-   (use (match_operand:SI 4 "arith_operand" "J,2"))     ;byte count
+   (use (match_operand:SI 4 "arith14_operand" "J,2"))   ;byte count
    (use (match_operand:SI 5 "const_int_operand" "n,n"))] ;alignment
   "!TARGET_64BIT"
   "#"
              (clobber (match_operand:SI 6 "register_operand" ""))
              (clobber (match_operand:SI 7 "register_operand" ""))
              (clobber (match_operand:SI 8 "register_operand" ""))
-             (use (match_operand:SI 4 "arith_operand" ""))
+             (use (match_operand:SI 4 "arith14_operand" ""))
              (use (match_operand:SI 5 "const_int_operand" ""))])]
   "!TARGET_64BIT && reload_completed && !flag_peephole2
    && GET_CODE (operands[0]) == MEM
              (clobber (match_operand:SI 6 "register_operand" ""))
              (clobber (match_operand:SI 7 "register_operand" ""))
              (clobber (match_operand:SI 8 "register_operand" ""))
-             (use (match_operand:SI 4 "arith_operand" ""))
+             (use (match_operand:SI 4 "arith14_operand" ""))
              (use (match_operand:SI 5 "const_int_operand" ""))])]
   "!TARGET_64BIT
    && GET_CODE (operands[0]) == MEM
     operands[7] = addr;
   else
     {
-      emit_insn (gen_rtx_SET (VOIDmode, operands[7], addr));
+      emit_insn (gen_rtx_SET (operands[7], addr));
       operands[0] = replace_equiv_address (operands[0], operands[7]);
     }
 
     operands[8] = addr;
   else
     {
-      emit_insn (gen_rtx_SET (VOIDmode, operands[8], addr));
+      emit_insn (gen_rtx_SET (operands[8], addr));
       operands[1] = replace_equiv_address (operands[1], operands[8]);
     }
 }")
 
-(define_insn "movmemsi_postreload"
+(define_insn "cpymemsi_postreload"
   [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r,r"))
        (mem:BLK (match_operand:SI 1 "register_operand" "+r,r")))
    (clobber (match_operand:SI 2 "register_operand" "=&r,&r"))  ;loop cnt/tmp
    (clobber (match_operand:SI 6 "register_operand" "=&r,&r"))  ;item tmp2
    (clobber (match_dup 0))
    (clobber (match_dup 1))
-   (use (match_operand:SI 4 "arith_operand" "J,2"))     ;byte count
+   (use (match_operand:SI 4 "arith14_operand" "J,2"))   ;byte count
    (use (match_operand:SI 5 "const_int_operand" "n,n"))  ;alignment
    (const_int 0)]
   "!TARGET_64BIT && reload_completed"
-  "* return output_block_move (operands, !which_alternative);"
+  "* return pa_output_block_move (operands, !which_alternative);"
   [(set_attr "type" "multi,multi")])
 
-(define_expand "movmemdi"
+(define_expand "cpymemdi"
   [(parallel [(set (match_operand:BLK 0 "" "")
                   (match_operand:BLK 1 "" ""))
              (clobber (match_dup 4))
              (clobber (match_dup 6))
              (clobber (match_dup 7))
              (clobber (match_dup 8))
-             (use (match_operand:DI 2 "arith_operand" ""))
+             (use (match_operand:DI 2 "arith14_operand" ""))
              (use (match_operand:DI 3 "const_int_operand" ""))])]
   "TARGET_64BIT && optimize > 0"
   "
 }")
 
 ;; The operand constraints are written like this to support both compile-time
-;; and run-time determined byte counts.  The expander and output_block_move
+;; and run-time determined byte counts.  The expander and pa_output_block_move
 ;; only support compile-time determined counts at this time.
 ;;
 ;; If the count is run-time determined, the register with the byte count
 ;; operands 0 and 1 are both equivalent to symbolic MEMs.  Thus, we are
 ;; forced to internally copy operands 0 and 1 to operands 7 and 8,
 ;; respectively.  We then split or peephole optimize after reload.
-(define_insn "movmemdi_prereload"
+(define_insn "cpymemdi_prereload"
   [(set (mem:BLK (match_operand:DI 0 "register_operand" "r,r"))
        (mem:BLK (match_operand:DI 1 "register_operand" "r,r")))
    (clobber (match_operand:DI 2 "register_operand" "=&r,&r"))  ;loop cnt/tmp
    (clobber (match_operand:DI 6 "register_operand" "=&r,&r"))  ;item tmp2
    (clobber (match_operand:DI 7 "register_operand" "=&r,&r"))  ;item tmp3
    (clobber (match_operand:DI 8 "register_operand" "=&r,&r"))  ;item tmp4
-   (use (match_operand:DI 4 "arith_operand" "J,2"))     ;byte count
+   (use (match_operand:DI 4 "arith14_operand" "J,2"))   ;byte count
    (use (match_operand:DI 5 "const_int_operand" "n,n"))] ;alignment
   "TARGET_64BIT"
   "#"
              (clobber (match_operand:DI 6 "register_operand" ""))
              (clobber (match_operand:DI 7 "register_operand" ""))
              (clobber (match_operand:DI 8 "register_operand" ""))
-             (use (match_operand:DI 4 "arith_operand" ""))
+             (use (match_operand:DI 4 "arith14_operand" ""))
              (use (match_operand:DI 5 "const_int_operand" ""))])]
   "TARGET_64BIT && reload_completed && !flag_peephole2
    && GET_CODE (operands[0]) == MEM
              (clobber (match_operand:DI 6 "register_operand" ""))
              (clobber (match_operand:DI 7 "register_operand" ""))
              (clobber (match_operand:DI 8 "register_operand" ""))
-             (use (match_operand:DI 4 "arith_operand" ""))
+             (use (match_operand:DI 4 "arith14_operand" ""))
              (use (match_operand:DI 5 "const_int_operand" ""))])]
   "TARGET_64BIT
    && GET_CODE (operands[0]) == MEM
     operands[7] = addr;
   else
     {
-      emit_insn (gen_rtx_SET (VOIDmode, operands[7], addr));
+      emit_insn (gen_rtx_SET (operands[7], addr));
       operands[0] = replace_equiv_address (operands[0], operands[7]);
     }
 
     operands[8] = addr;
   else
     {
-      emit_insn (gen_rtx_SET (VOIDmode, operands[8], addr));
+      emit_insn (gen_rtx_SET (operands[8], addr));
       operands[1] = replace_equiv_address (operands[1], operands[8]);
     }
 }")
 
-(define_insn "movmemdi_postreload"
+(define_insn "cpymemdi_postreload"
   [(set (mem:BLK (match_operand:DI 0 "register_operand" "+r,r"))
        (mem:BLK (match_operand:DI 1 "register_operand" "+r,r")))
    (clobber (match_operand:DI 2 "register_operand" "=&r,&r"))  ;loop cnt/tmp
    (clobber (match_operand:DI 6 "register_operand" "=&r,&r"))  ;item tmp2
    (clobber (match_dup 0))
    (clobber (match_dup 1))
-   (use (match_operand:DI 4 "arith_operand" "J,2"))     ;byte count
+   (use (match_operand:DI 4 "arith14_operand" "J,2"))   ;byte count
    (use (match_operand:DI 5 "const_int_operand" "n,n"))  ;alignment
    (const_int 0)]
   "TARGET_64BIT && reload_completed"
-  "* return output_block_move (operands, !which_alternative);"
+  "* return pa_output_block_move (operands, !which_alternative);"
   [(set_attr "type" "multi,multi")])
 
 (define_expand "setmemsi"
                   (match_operand 2 "const_int_operand" ""))
              (clobber (match_dup 4))
              (clobber (match_dup 5))
-             (use (match_operand:SI 1 "arith_operand" ""))
+             (use (match_operand:SI 1 "arith14_operand" ""))
              (use (match_operand:SI 3 "const_int_operand" ""))])]
   "!TARGET_64BIT && optimize > 0"
   "
        (const_int 0))
    (clobber (match_operand:SI 1 "register_operand" "=&r,&r"))  ;loop cnt/tmp
    (clobber (match_operand:SI 4 "register_operand" "=&r,&r"))  ;tmp1
-   (use (match_operand:SI 2 "arith_operand" "J,1"))     ;byte count
+   (use (match_operand:SI 2 "arith14_operand" "J,1"))   ;byte count
    (use (match_operand:SI 3 "const_int_operand" "n,n"))] ;alignment
   "!TARGET_64BIT"
   "#"
                   (const_int 0))
              (clobber (match_operand:SI 1 "register_operand" ""))
              (clobber (match_operand:SI 4 "register_operand" ""))
-             (use (match_operand:SI 2 "arith_operand" ""))
+             (use (match_operand:SI 2 "arith14_operand" ""))
              (use (match_operand:SI 3 "const_int_operand" ""))])]
   "!TARGET_64BIT && reload_completed && !flag_peephole2
    && GET_CODE (operands[0]) == MEM
                   (const_int 0))
              (clobber (match_operand:SI 1 "register_operand" ""))
              (clobber (match_operand:SI 4 "register_operand" ""))
-             (use (match_operand:SI 2 "arith_operand" ""))
+             (use (match_operand:SI 2 "arith14_operand" ""))
              (use (match_operand:SI 3 "const_int_operand" ""))])]
   "!TARGET_64BIT
    && GET_CODE (operands[0]) == MEM
     operands[4] = addr;
   else
     {
-      emit_insn (gen_rtx_SET (VOIDmode, operands[4], addr));
+      emit_insn (gen_rtx_SET (operands[4], addr));
       operands[0] = replace_equiv_address (operands[0], operands[4]);
     }
 }")
        (const_int 0))
    (clobber (match_operand:SI 1 "register_operand" "=&r,&r"))  ;loop cnt/tmp
    (clobber (match_dup 0))
-   (use (match_operand:SI 2 "arith_operand" "J,1"))     ;byte count
+   (use (match_operand:SI 2 "arith14_operand" "J,1"))   ;byte count
    (use (match_operand:SI 3 "const_int_operand" "n,n"))  ;alignment
    (const_int 0)]
   "!TARGET_64BIT && reload_completed"
-  "* return output_block_clear (operands, !which_alternative);"
+  "* return pa_output_block_clear (operands, !which_alternative);"
   [(set_attr "type" "multi,multi")])
 
 (define_expand "setmemdi"
                   (match_operand 2 "const_int_operand" ""))
              (clobber (match_dup 4))
              (clobber (match_dup 5))
-             (use (match_operand:DI 1 "arith_operand" ""))
+             (use (match_operand:DI 1 "arith14_operand" ""))
              (use (match_operand:DI 3 "const_int_operand" ""))])]
   "TARGET_64BIT && optimize > 0"
   "
        (const_int 0))
    (clobber (match_operand:DI 1 "register_operand" "=&r,&r"))  ;loop cnt/tmp
    (clobber (match_operand:DI 4 "register_operand" "=&r,&r"))  ;item tmp1
-   (use (match_operand:DI 2 "arith_operand" "J,1"))     ;byte count
+   (use (match_operand:DI 2 "arith14_operand" "J,1"))   ;byte count
    (use (match_operand:DI 3 "const_int_operand" "n,n"))] ;alignment
   "TARGET_64BIT"
   "#"
                   (const_int 0))
              (clobber (match_operand:DI 1 "register_operand" ""))
              (clobber (match_operand:DI 4 "register_operand" ""))
-             (use (match_operand:DI 2 "arith_operand" ""))
+             (use (match_operand:DI 2 "arith14_operand" ""))
              (use (match_operand:DI 3 "const_int_operand" ""))])]
   "TARGET_64BIT && reload_completed && !flag_peephole2
    && GET_CODE (operands[0]) == MEM
                   (const_int 0))
              (clobber (match_operand:DI 1 "register_operand" ""))
              (clobber (match_operand:DI 4 "register_operand" ""))
-             (use (match_operand:DI 2 "arith_operand" ""))
+             (use (match_operand:DI 2 "arith14_operand" ""))
              (use (match_operand:DI 3 "const_int_operand" ""))])]
   "TARGET_64BIT
    && GET_CODE (operands[0]) == MEM
     operands[4] = addr;
   else
     {
-      emit_insn (gen_rtx_SET (VOIDmode, operands[4], addr));
+      emit_insn (gen_rtx_SET (operands[4], addr));
       operands[0] = replace_equiv_address (operands[0], operands[4]);
     }
 }")
        (const_int 0))
    (clobber (match_operand:DI 1 "register_operand" "=&r,&r"))  ;loop cnt/tmp
    (clobber (match_dup 0))
-   (use (match_operand:DI 2 "arith_operand" "J,1"))     ;byte count
+   (use (match_operand:DI 2 "arith14_operand" "J,1"))   ;byte count
    (use (match_operand:DI 3 "const_int_operand" "n,n"))  ;alignment
    (const_int 0)]
   "TARGET_64BIT && reload_completed"
-  "* return output_block_clear (operands, !which_alternative);"
+  "* return pa_output_block_clear (operands, !which_alternative);"
   [(set_attr "type" "multi,multi")])
 \f
 ;; Floating point move insns
 
-;; This pattern forces (set (reg:DF ...) (const_double ...))
-;; to be reloaded by putting the constant into memory when
-;; reg is a floating point register.
-;;
-;; For integer registers we use ldil;ldo to set the appropriate
-;; value.
-;;
-;; This must come before the movdf pattern, and it must be present
-;; to handle obscure reloading cases.
-(define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=?r,f")
-       (match_operand:DF 1 "" "?F,m"))]
-  "GET_CODE (operands[1]) == CONST_DOUBLE
-   && operands[1] != CONST0_RTX (DFmode)
-   && !TARGET_64BIT
-   && !TARGET_SOFT_FLOAT"
-  "* return (which_alternative == 0 ? output_move_double (operands)
-                                   : \"fldd%F1 %1,%0\");"
-  [(set_attr "type" "move,fpload")
-   (set_attr "length" "16,4")])
-
 (define_expand "movdf"
   [(set (match_operand:DF 0 "general_operand" "")
        (match_operand:DF 1 "general_operand" ""))]
   ""
   "
 {
-  if (GET_CODE (operands[1]) == CONST_DOUBLE
-      && operands[1] != CONST0_RTX (DFmode))
-    {
-      /* Reject CONST_DOUBLE loads to all hard registers when
-        generating 64-bit code and to floating point registers
-        when generating 32-bit code.  */
-      if (REG_P (operands[0])
-         && HARD_REGISTER_P (operands[0])
-         && (TARGET_64BIT || REGNO (operands[0]) >= 32))
-       FAIL;
-
-      if (TARGET_64BIT)
-       operands[1] = force_const_mem (DFmode, operands[1]);
-    }
+  if (pa_emit_move_sequence (operands, DFmode, 0))
+    DONE;
+}")
 
-  if (emit_move_sequence (operands, DFmode, 0))
+;; Handle DFmode input reloads requiring %r1 as a scratch register.
+(define_expand "reload_indf_r1"
+  [(set (match_operand:DF 0 "register_operand" "=Z")
+       (match_operand:DF 1 "non_hard_reg_operand" ""))
+   (clobber (match_operand:SI 2 "register_operand" "=&a"))]
+  ""
+  "
+{
+  if (pa_emit_move_sequence (operands, DFmode, operands[2]))
     DONE;
+
+  /* We don't want the clobber emitted, so handle this ourselves.  */
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
+  DONE;
 }")
 
 ;; Handle DFmode input reloads requiring a general register as a
   ""
   "
 {
-  if (emit_move_sequence (operands, DFmode, operands[2]))
+  if (pa_emit_move_sequence (operands, DFmode, operands[2]))
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves.  */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 }")
 
   ""
   "
 {
-  if (emit_move_sequence (operands, DFmode, operands[2]))
+  if (pa_emit_move_sequence (operands, DFmode, operands[2]))
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves.  */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 }")
 
 (define_insn ""
   [(set (match_operand:DF 0 "move_dest_operand"
-                         "=f,*r,Q,?o,?Q,f,*r,*r,?*r,?f")
+                         "=f,*r,T,?o,?Q,f,*r,*r,?*r,?f")
        (match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand"
-                         "fG,*rG,f,*r,*r,RQ,o,RQ,f,*r"))]
+                         "fG,*rG,f,*r,*r,RT,o,RQ,f,*r"))]
   "(register_operand (operands[0], DFmode)
     || reg_or_0_operand (operands[1], DFmode))
    && !(GET_CODE (operands[1]) == CONST_DOUBLE
        || operands[1] == CONST0_RTX (DFmode))
       && !(REG_P (operands[0]) && REG_P (operands[1])
           && FP_REG_P (operands[0]) ^ FP_REG_P (operands[1])))
-    return output_fp_move_double (operands);
-  return output_move_double (operands);
+    return pa_output_fp_move_double (operands);
+  return pa_output_move_double (operands);
 }"
   [(set_attr "type" "fpalu,move,fpstore,store,store,fpload,load,load,fpstore_load,store_fpload")
    (set_attr "length" "4,8,4,8,16,4,8,16,12,12")])
 
 (define_peephole2
   [(set (match_operand:SI 0 "register_operand" "")
-       (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "")
-                         (const_int 8))
+       (plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
+                           (const_int 3))
                 (match_operand:SI 2 "register_operand" "")))
    (set (mem:DF (match_dup 0))
         (match_operand:DF 3 "register_operand" ""))]
    && FP_REGNO_P (REGNO (operands[3]))"
   [(set (mem:DF (plus:SI (mult:SI (match_dup 1) (const_int 8)) (match_dup 2)))
        (match_dup 3))
-   (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 8))
+   (set (match_dup 0) (plus:SI (ashift:SI (match_dup 1) (const_int 3))
                               (match_dup 2)))]
   "")
 
 (define_peephole2
   [(set (match_operand:SI 0 "register_operand" "")
        (plus:SI (match_operand:SI 2 "register_operand" "")
-                (mult:SI (match_operand:SI 1 "register_operand" "")
-                         (const_int 8))))
+                (ashift:SI (match_operand:SI 1 "register_operand" "")
+                           (const_int 3))))
    (set (mem:DF (match_dup 0))
         (match_operand:DF 3 "register_operand" ""))]
   "!TARGET_SOFT_FLOAT
    && FP_REGNO_P (REGNO (operands[3]))"
   [(set (mem:DF (plus:SI (mult:SI (match_dup 1) (const_int 8)) (match_dup 2)))
        (match_dup 3))
-   (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 8))
+   (set (match_dup 0) (plus:SI (ashift:SI (match_dup 1) (const_int 3))
                               (match_dup 2)))]
   "")
 
 (define_peephole2
   [(set (match_operand:DI 0 "register_operand" "")
-       (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "")
-                         (const_int 8))
+       (plus:DI (ashift:DI (match_operand:DI 1 "register_operand" "")
+                           (const_int 3))
                 (match_operand:DI 2 "register_operand" "")))
    (set (mem:DF (match_dup 0))
         (match_operand:DF 3 "register_operand" ""))]
    && FP_REGNO_P (REGNO (operands[3]))"
   [(set (mem:DF (plus:DI (mult:DI (match_dup 1) (const_int 8)) (match_dup 2)))
        (match_dup 3))
-   (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 8))
+   (set (match_dup 0) (plus:DI (ashift:DI (match_dup 1) (const_int 3))
                               (match_dup 2)))]
   "")
 
 (define_peephole2
   [(set (match_operand:DI 0 "register_operand" "")
        (plus:DI (match_operand:DI 2 "register_operand" "")
-                (mult:DI (match_operand:DI 1 "register_operand" "")
-                         (const_int 8))))
+                (ashift:DI (match_operand:DI 1 "register_operand" "")
+                           (const_int 3))))
    (set (mem:DF (match_dup 0))
         (match_operand:DF 3 "register_operand" ""))]
   "!TARGET_SOFT_FLOAT
    && FP_REGNO_P (REGNO (operands[3]))"
   [(set (mem:DF (plus:DI (mult:DI (match_dup 1) (const_int 8)) (match_dup 2)))
        (match_dup 3))
-   (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 8))
+   (set (match_dup 0) (plus:DI (ashift:DI (match_dup 1) (const_int 3))
                               (match_dup 2)))]
   "")
 
    && TARGET_SOFT_FLOAT"
   "*
 {
-  return output_move_double (operands);
+  return pa_output_move_double (operands);
 }"
   [(set_attr "type" "move,store,store,load,load")
    (set_attr "length" "8,8,16,8,16")])
   ""
   "
 {
-  /* Except for zero, we don't support loading a CONST_INT directly
-     to a hard floating-point register since a scratch register is
-     needed for the operation.  While the operation could be handled
-     before register allocation, the simplest solution is to fail.  */
-  if (TARGET_64BIT
-      && GET_CODE (operands[1]) == CONST_INT
-      && operands[1] != CONST0_RTX (DImode)
-      && REG_P (operands[0])
-      && HARD_REGISTER_P (operands[0])
-      && REGNO (operands[0]) >= 32)
-    FAIL;
-
-  if (emit_move_sequence (operands, DImode, 0))
+  if (pa_emit_move_sequence (operands, DImode, 0))
     DONE;
 }")
 
   ""
   "
 {
-  if (emit_move_sequence (operands, DImode, operands[2]))
+  if (pa_emit_move_sequence (operands, DImode, operands[2]))
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves.  */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 }")
 
   ""
   "
 {
-  if (emit_move_sequence (operands, DImode, operands[2]))
+  if (pa_emit_move_sequence (operands, DImode, operands[2]))
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves.  */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 }")
 
   ""
   "
 {
-  if (emit_move_sequence (operands, DImode, operands[2]))
+  if (pa_emit_move_sequence (operands, DImode, operands[2]))
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves.  */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 }")
 
 
       operands[0] = operand_subword (op0, 0, 0, DImode);
       operands[1] = GEN_INT (INTVAL (op1) >> 32);
-      output_asm_insn (singlemove_string (operands), operands);
+      output_asm_insn (pa_singlemove_string (operands), operands);
 #endif
       break;
 
 
       operands[0] = operand_subword (op0, 0, 0, DImode);
       operands[1] = GEN_INT (CONST_DOUBLE_HIGH (op1));
-      output_asm_insn (singlemove_string (operands), operands);
+      output_asm_insn (pa_singlemove_string (operands), operands);
       break;
 
     default:
 (define_insn ""
   [(set (match_operand:DI 0 "move_dest_operand"
                          "=r,o,Q,r,r,r,*f,*f,T,?r,?*f")
-       (match_operand:DI 1 "general_operand"
+       (match_operand:DI 1 "move_src_operand"
                          "rM,r,r,o*R,Q,i,*fM,RT,*f,*f,r"))]
   "(register_operand (operands[0], DImode)
     || reg_or_0_operand (operands[1], DImode))
        || operands[1] == CONST0_RTX (DFmode))
       && !(REG_P (operands[0]) && REG_P (operands[1])
           && FP_REG_P (operands[0]) ^ FP_REG_P (operands[1])))
-    return output_fp_move_double (operands);
-  return output_move_double (operands);
+    return pa_output_fp_move_double (operands);
+  return pa_output_move_double (operands);
 }"
   [(set_attr "type"
     "move,store,store,load,load,multi,fpalu,fpload,fpstore,fpstore_load,store_fpload")
 
 (define_peephole2
   [(set (match_operand:DI 0 "register_operand" "")
-       (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "")
-                         (const_int 8))
+       (plus:DI (ashift:DI (match_operand:DI 1 "register_operand" "")
+                           (const_int 3))
                 (match_operand:DI 2 "register_operand" "")))
    (set (mem:DI (match_dup 0))
         (match_operand:DI 3 "register_operand" ""))]
    && FP_REGNO_P (REGNO (operands[3]))"
   [(set (mem:DI (plus:DI (mult:DI (match_dup 1) (const_int 8)) (match_dup 2)))
        (match_dup 3))
-   (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 8))
-                              (match_dup 2)))]
-  "")
-
-(define_peephole2
-  [(set (match_operand:DI 0 "register_operand" "")
-       (plus:DI (match_operand:DI 2 "register_operand" "")
-                (mult:DI (match_operand:DI 1 "register_operand" "")
-                         (const_int 8))))
-   (set (mem:DI (match_dup 0))
-        (match_operand:DI 3 "register_operand" ""))]
-  "!TARGET_SOFT_FLOAT
-   && !TARGET_DISABLE_INDEXING
-   && TARGET_64BIT
-   && REG_OK_FOR_BASE_P (operands[2])
-   && FP_REGNO_P (REGNO (operands[3]))"
-  [(set (mem:DI (plus:DI (mult:DI (match_dup 1) (const_int 8)) (match_dup 2)))
-       (match_dup 3))
-   (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 8))
+   (set (match_dup 0) (plus:DI (ashift:DI (match_dup 1) (const_int 3))
                               (match_dup 2)))]
   "")
 
    && TARGET_SOFT_FLOAT"
   "*
 {
-  return output_move_double (operands);
+  return pa_output_move_double (operands);
 }"
   [(set_attr "type" "move,store,store,load,load,multi")
    (set_attr "length" "8,8,16,8,16,16")])
   [(set_attr "type" "move,move")
    (set_attr "length" "4,8")])
 
-;; This pattern forces (set (reg:SF ...) (const_double ...))
-;; to be reloaded by putting the constant into memory when
-;; reg is a floating point register.
-;;
-;; For integer registers we use ldil;ldo to set the appropriate
-;; value.
-;;
-;; This must come before the movsf pattern, and it must be present
-;; to handle obscure reloading cases.
-(define_insn ""
-  [(set (match_operand:SF 0 "register_operand" "=?r,f")
-       (match_operand:SF 1 "" "?F,m"))]
-  "GET_CODE (operands[1]) == CONST_DOUBLE
-   && operands[1] != CONST0_RTX (SFmode)
-   && ! TARGET_SOFT_FLOAT"
-  "* return (which_alternative == 0 ? singlemove_string (operands)
-                                   : \" fldw%F1 %1,%0\");"
-  [(set_attr "type" "move,fpload")
-   (set_attr "length" "8,4")])
-
 (define_expand "movsf"
   [(set (match_operand:SF 0 "general_operand" "")
        (match_operand:SF 1 "general_operand" ""))]
   ""
   "
 {
-  /* Reject CONST_DOUBLE loads to floating point registers.  */
-  if (GET_CODE (operands[1]) == CONST_DOUBLE
-      && operands[1] != CONST0_RTX (SFmode)
-      && REG_P (operands[0])
-      && HARD_REGISTER_P (operands[0])
-      && REGNO (operands[0]) >= 32)
-    FAIL;
+  if (pa_emit_move_sequence (operands, SFmode, 0))
+    DONE;
+}")
 
-  if (emit_move_sequence (operands, SFmode, 0))
+;; Handle SFmode input reloads requiring %r1 as a scratch register.
+(define_expand "reload_insf_r1"
+  [(set (match_operand:SF 0 "register_operand" "=Z")
+       (match_operand:SF 1 "non_hard_reg_operand" ""))
+   (clobber (match_operand:SI 2 "register_operand" "=&a"))]
+  ""
+  "
+{
+  if (pa_emit_move_sequence (operands, SFmode, operands[2]))
     DONE;
+
+  /* We don't want the clobber emitted, so handle this ourselves.  */
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
+  DONE;
 }")
 
 ;; Handle SFmode input reloads requiring a general register as a
   ""
   "
 {
-  if (emit_move_sequence (operands, SFmode, operands[2]))
+  if (pa_emit_move_sequence (operands, SFmode, operands[2]))
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves.  */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 }")
 
   ""
   "
 {
-  if (emit_move_sequence (operands, SFmode, operands[2]))
+  if (pa_emit_move_sequence (operands, SFmode, operands[2]))
     DONE;
 
   /* We don't want the clobber emitted, so handle this ourselves.  */
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
   DONE;
 }")
 
 (define_insn ""
   [(set (match_operand:SF 0 "move_dest_operand"
-                         "=f,!*r,f,*r,Q,Q,?*r,?f")
+                         "=f,!*r,f,*r,T,Q,?*r,?f")
        (match_operand:SF 1 "reg_or_0_or_nonsymb_mem_operand"
-                         "fG,!*rG,RQ,RQ,f,*rG,f,*r"))]
+                         "fG,!*rG,RT,RQ,f,*rG,f,*r"))]
   "(register_operand (operands[0], SFmode)
     || reg_or_0_operand (operands[1], SFmode))
    && !TARGET_SOFT_FLOAT
 
 (define_insn ""
   [(set (match_operand:SF 0 "move_dest_operand"
-                         "=f,!*r,f,*r,Q,Q")
+                         "=f,!*r,f,*r,T,Q")
        (match_operand:SF 1 "reg_or_0_or_nonsymb_mem_operand"
-                         "fG,!*rG,RQ,RQ,f,*rG"))]
+                         "fG,!*rG,RT,RQ,f,*rG"))]
   "(register_operand (operands[0], SFmode)
     || reg_or_0_operand (operands[1], SFmode))
    && !TARGET_SOFT_FLOAT
 
 (define_peephole2
   [(set (match_operand:SI 0 "register_operand" "")
-       (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "")
-                         (const_int 4))
+       (plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
+                           (const_int 2))
                 (match_operand:SI 2 "register_operand" "")))
    (set (mem:SF (match_dup 0))
         (match_operand:SF 3 "register_operand" ""))]
    && FP_REGNO_P (REGNO (operands[3]))"
   [(set (mem:SF (plus:SI (mult:SI (match_dup 1) (const_int 4)) (match_dup 2)))
        (match_dup 3))
-   (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 4))
-                              (match_dup 2)))]
-  "")
-
-(define_peephole2
-  [(set (match_operand:SI 0 "register_operand" "")
-       (plus:SI (match_operand:SI 2 "register_operand" "")
-                (mult:SI (match_operand:SI 1 "register_operand" "")
-                         (const_int 4))))
-   (set (mem:SF (match_dup 0))
-        (match_operand:SF 3 "register_operand" ""))]
-  "!TARGET_SOFT_FLOAT
-   && !TARGET_DISABLE_INDEXING
-   && REG_OK_FOR_BASE_P (operands[2])
-   && FP_REGNO_P (REGNO (operands[3]))"
-  [(set (mem:SF (plus:SI (mult:SI (match_dup 1) (const_int 4)) (match_dup 2)))
-       (match_dup 3))
-   (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 4))
+   (set (match_dup 0) (plus:SI (ashift:SI (match_dup 1) (const_int 2))
                               (match_dup 2)))]
   "")
 
 (define_peephole2
   [(set (match_operand:DI 0 "register_operand" "")
-       (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "")
-                         (const_int 4))
+       (plus:DI (ashift:DI (match_operand:DI 1 "register_operand" "")
+                           (const_int 2))
                 (match_operand:DI 2 "register_operand" "")))
    (set (mem:SF (match_dup 0))
         (match_operand:SF 3 "register_operand" ""))]
    && FP_REGNO_P (REGNO (operands[3]))"
   [(set (mem:SF (plus:DI (mult:DI (match_dup 1) (const_int 4)) (match_dup 2)))
        (match_dup 3))
-   (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 4))
-                              (match_dup 2)))]
-  "")
-
-(define_peephole2
-  [(set (match_operand:DI 0 "register_operand" "")
-       (plus:DI (match_operand:DI 2 "register_operand" "")
-                (mult:DI (match_operand:DI 1 "register_operand" "")
-                         (const_int 4))))
-   (set (mem:SF (match_dup 0))
-        (match_operand:SF 3 "register_operand" ""))]
-  "!TARGET_SOFT_FLOAT
-   && !TARGET_DISABLE_INDEXING
-   && TARGET_64BIT
-   && REG_OK_FOR_BASE_P (operands[2])
-   && FP_REGNO_P (REGNO (operands[3]))"
-  [(set (mem:SF (plus:DI (mult:DI (match_dup 1) (const_int 4)) (match_dup 2)))
-       (match_dup 3))
-   (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 4))
+   (set (match_dup 0) (plus:DI (ashift:DI (match_dup 1) (const_int 2))
                               (match_dup 2)))]
   "")
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r,r")
        (plus:DI (match_operand:DI 1 "register_operand" "%r,r")
-                (match_operand:DI 2 "arith_operand" "r,J")))]
+                (match_operand:DI 2 "arith14_operand" "r,J")))]
   "TARGET_64BIT"
   "@
    add,l %1,%2,%0
        (plus:SI (match_operand:SI 1 "register_operand" "")
                 (match_operand:SI 2 "const_int_operand" "")))
    (clobber (match_operand:SI 4 "register_operand" ""))]
-  "! cint_ok_for_move (INTVAL (operands[2]))
+  "! pa_cint_ok_for_move (UINTVAL (operands[2]))
    && VAL_14_BITS_P (INTVAL (operands[2]) >> 1)"
   [(set (match_dup 4) (plus:SI (match_dup 1) (match_dup 2)))
    (set (match_dup 0) (plus:SI (match_dup 4) (match_dup 3)))]
        (plus:SI (match_operand:SI 1 "register_operand" "")
                 (match_operand:SI 2 "const_int_operand" "")))
    (clobber (match_operand:SI 4 "register_operand" ""))]
-  "! cint_ok_for_move (INTVAL (operands[2]))"
+  "! pa_cint_ok_for_move (UINTVAL (operands[2]))"
   [(set (match_dup 4) (match_dup 2))
-   (set (match_dup 0) (plus:SI (mult:SI (match_dup 4) (match_dup 3))
+   (set (match_dup 0) (plus:SI (ashift:SI (match_dup 4) (match_dup 3))
                               (match_dup 1)))]
   "
 {
-  HOST_WIDE_INT intval = INTVAL (operands[2]);
+  unsigned HOST_WIDE_INT intval = UINTVAL (operands[2]);
 
   /* Try dividing the constant by 2, then 4, and finally 8 to see
      if we can get a constant which can be loaded into a register
-     in a single instruction (cint_ok_for_move). 
+     in a single instruction (pa_cint_ok_for_move). 
 
      If that fails, try to negate the constant and subtract it
      from our input operand.  */
-  if (intval % 2 == 0 && cint_ok_for_move (intval / 2))
+  if (intval % 2 == 0 && pa_cint_ok_for_move (intval / 2))
     {
       operands[2] = GEN_INT (intval / 2);
-      operands[3] = const2_rtx;
+      operands[3] = const1_rtx;
     }
-  else if (intval % 4 == 0 && cint_ok_for_move (intval / 4))
+  else if (intval % 4 == 0 && pa_cint_ok_for_move (intval / 4))
     {
       operands[2] = GEN_INT (intval / 4);
-      operands[3] = GEN_INT (4);
+      operands[3] = const2_rtx;
     }
-  else if (intval % 8 == 0 && cint_ok_for_move (intval / 8))
+  else if (intval % 8 == 0 && pa_cint_ok_for_move (intval / 8))
     {
       operands[2] = GEN_INT (intval / 8);
-      operands[3] = GEN_INT (8);
+      operands[3] = GEN_INT (3);
     }
-  else if (cint_ok_for_move (-intval))
+  else if (pa_cint_ok_for_move (-intval))
     {
-      emit_insn (gen_rtx_SET (VOIDmode, operands[4], GEN_INT (-intval)));
+      emit_insn (gen_rtx_SET (operands[4], GEN_INT (-intval)));
       emit_insn (gen_subsi3 (operands[0], operands[1], operands[4]));
       DONE;
     }
 (define_insn "addsi3"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (plus:SI (match_operand:SI 1 "register_operand" "%r,r")
-                (match_operand:SI 2 "arith_operand" "r,J")))]
+                (match_operand:SI 2 "arith14_operand" "r,J")))]
   ""
   "@
    {addl|add,l} %1,%2,%0
   [(set_attr "type" "binary,binary")
    (set_attr "length" "4,4")])
 
+;; Trap instructions.
+
+(define_insn "trap"
+  [(trap_if (const_int 1) (const_int 0))]
+  ""
+  "{addit|addi,tc},<> 1,%%r0,%%r0"
+  [(set_attr "type" "trap")
+   (set_attr "length" "4")])
+
 ;; Clobbering a "register_operand" instead of a match_scratch
 ;; in operand3 of millicode calls avoids spilling %r1 and
 ;; produces better code.
 }")
 
 (define_insn "umulsidi3"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=f")
-       (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f"))
-                (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "f"))))]
+  [(set (match_operand:DI 0 "register_operand" "=f")
+       (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "f"))
+                (zero_extend:DI (match_operand:SI 2 "register_operand" "f"))))]
   "TARGET_PA_11 && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT"
   "xmpyu %1,%2,%0"
   [(set_attr "type" "fpmuldbl")
    (set_attr "length" "4")])
 
 (define_insn ""
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=f")
-       (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f"))
+  [(set (match_operand:DI 0 "register_operand" "=f")
+       (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "f"))
                 (match_operand:DI 2 "uint32_operand" "f")))]
   "TARGET_PA_11 && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT && !TARGET_64BIT"
   "xmpyu %1,%R2,%0"
    (set_attr "length" "4")])
 
 (define_insn ""
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=f")
-       (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f"))
+  [(set (match_operand:DI 0 "register_operand" "=f")
+       (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "f"))
                 (match_operand:DI 2 "uint32_operand" "f")))]
   "TARGET_PA_11 && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT && TARGET_64BIT"
   "xmpyu %1,%2R,%0"
    (clobber (reg:SI 25))
    (clobber (reg:SI 31))]
   "!TARGET_64BIT"
-  "* return output_mul_insn (0, insn);"
+  "* return pa_output_mul_insn (0, insn);"
   [(set_attr "type" "milli")
-   (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_millicode_call (insn)")))])
 
 (define_insn ""
   [(set (reg:SI 29) (mult:SI (reg:SI 26) (reg:SI 25)))
    (clobber (reg:SI 25))
    (clobber (reg:SI 2))]
   "TARGET_64BIT"
-  "* return output_mul_insn (0, insn);"
+  "* return pa_output_mul_insn (0, insn);"
   [(set_attr "type" "milli")
-   (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_millicode_call (insn)")))])
 
 (define_expand "muldi3"
   [(set (match_operand:DI 0 "register_operand" "")
       operands[5] = gen_rtx_REG (SImode, 31);
       operands[4] = gen_reg_rtx (SImode);
     }
-  if (GET_CODE (operands[2]) == CONST_INT && emit_hpdiv_const (operands, 0))
+  if (GET_CODE (operands[2]) == CONST_INT && pa_emit_hpdiv_const (operands, 0))
     DONE;
 }")
 
    (clobber (reg:SI 31))]
   "!TARGET_64BIT"
   "*
-   return output_div_insn (operands, 0, insn);"
+   return pa_output_div_insn (operands, 0, insn);"
   [(set_attr "type" "milli")
-   (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_millicode_call (insn)")))])
 
 (define_insn ""
   [(set (reg:SI 29)
    (clobber (reg:SI 2))]
   "TARGET_64BIT"
   "*
-   return output_div_insn (operands, 0, insn);"
+   return pa_output_div_insn (operands, 0, insn);"
   [(set_attr "type" "milli")
-   (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_millicode_call (insn)")))])
 
 (define_expand "udivsi3"
   [(set (reg:SI 26) (match_operand:SI 1 "move_src_operand" ""))
       operands[5] = gen_rtx_REG (SImode, 31);
       operands[4] = gen_reg_rtx (SImode);
     }
-  if (GET_CODE (operands[2]) == CONST_INT && emit_hpdiv_const (operands, 1))
+  if (GET_CODE (operands[2]) == CONST_INT && pa_emit_hpdiv_const (operands, 1))
     DONE;
 }")
 
    (clobber (reg:SI 31))]
   "!TARGET_64BIT"
   "*
-   return output_div_insn (operands, 1, insn);"
+   return pa_output_div_insn (operands, 1, insn);"
   [(set_attr "type" "milli")
-   (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_millicode_call (insn)")))])
 
 (define_insn ""
   [(set (reg:SI 29)
    (clobber (reg:SI 2))]
   "TARGET_64BIT"
   "*
-   return output_div_insn (operands, 1, insn);"
+   return pa_output_div_insn (operands, 1, insn);"
   [(set_attr "type" "milli")
-   (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_millicode_call (insn)")))])
 
 (define_expand "modsi3"
   [(set (reg:SI 26) (match_operand:SI 1 "move_src_operand" ""))
    (clobber (reg:SI 31))]
   "!TARGET_64BIT"
   "*
-  return output_mod_insn (0, insn);"
+  return pa_output_mod_insn (0, insn);"
   [(set_attr "type" "milli")
-   (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_millicode_call (insn)")))])
 
 (define_insn ""
   [(set (reg:SI 29) (mod:SI (reg:SI 26) (reg:SI 25)))
    (clobber (reg:SI 2))]
   "TARGET_64BIT"
   "*
-  return output_mod_insn (0, insn);"
+  return pa_output_mod_insn (0, insn);"
   [(set_attr "type" "milli")
-   (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_millicode_call (insn)")))])
 
 (define_expand "umodsi3"
   [(set (reg:SI 26) (match_operand:SI 1 "move_src_operand" ""))
    (clobber (reg:SI 31))]
   "!TARGET_64BIT"
   "*
-  return output_mod_insn (1, insn);"
+  return pa_output_mod_insn (1, insn);"
   [(set_attr "type" "milli")
-   (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_millicode_call (insn)")))])
 
 (define_insn ""
   [(set (reg:SI 29) (umod:SI (reg:SI 26) (reg:SI 25)))
    (clobber (reg:SI 2))]
   "TARGET_64BIT"
   "*
-  return output_mod_insn (1, insn);"
+  return pa_output_mod_insn (1, insn);"
   [(set_attr "type" "milli")
-   (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_millicode_call (insn)")))])
 
 ;;- and instructions
 ;; We define DImode `and` so with DImode `not` we can get
   [(set (match_operand:DI 0 "register_operand" "")
        (and:DI (match_operand:DI 1 "register_operand" "")
                (match_operand:DI 2 "and_operand" "")))]
-  ""
-  "
-{
-  /* Both operands must be register operands.  */
-  if (!TARGET_64BIT && !register_operand (operands[2], DImode))
-    FAIL;
-}")
-
-(define_insn ""
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (and:DI (match_operand:DI 1 "register_operand" "%r")
-               (match_operand:DI 2 "register_operand" "r")))]
-  "!TARGET_64BIT"
-  "and %1,%2,%0\;and %R1,%R2,%R0"
-  [(set_attr "type" "binary")
-   (set_attr "length" "8")])
+  "TARGET_64BIT"
+  "")
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r,r")
        (and:DI (match_operand:DI 1 "register_operand" "%?r,0")
                (match_operand:DI 2 "and_operand" "rO,P")))]
   "TARGET_64BIT"
-  "* return output_64bit_and (operands); "
+  "* return pa_output_64bit_and (operands); "
   [(set_attr "type" "binary")
    (set_attr "length" "4")])
 
        (and:SI (match_operand:SI 1 "register_operand" "%?r,0")
                (match_operand:SI 2 "and_operand" "rO,P")))]
   ""
-  "* return output_and (operands); "
+  "* return pa_output_and (operands); "
   [(set_attr "type" "binary,shift")
    (set_attr "length" "4,4")])
 
-(define_insn ""
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
-               (match_operand:DI 2 "register_operand" "r")))]
-  "!TARGET_64BIT"
-  "andcm %2,%1,%0\;andcm %R2,%R1,%R0"
-  [(set_attr "type" "binary")
-   (set_attr "length" "8")])
-
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
        (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
 (define_expand "iordi3"
   [(set (match_operand:DI 0 "register_operand" "")
        (ior:DI (match_operand:DI 1 "register_operand" "")
-               (match_operand:DI 2 "ior_operand" "")))]
-  ""
-  "
-{
-  /* Both operands must be register operands.  */
-  if (!TARGET_64BIT && !register_operand (operands[2], DImode))
-    FAIL;
-}")
-
-(define_insn ""
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (ior:DI (match_operand:DI 1 "register_operand" "%r")
-               (match_operand:DI 2 "register_operand" "r")))]
-  "!TARGET_64BIT"
-  "or %1,%2,%0\;or %R1,%R2,%R0"
-  [(set_attr "type" "binary")
-   (set_attr "length" "8")])
+               (match_operand:DI 2 "reg_or_cint_ior_operand" "")))]
+  "TARGET_64BIT"
+  "")
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r,r")
        (ior:DI (match_operand:DI 1 "register_operand" "0,0")
-               (match_operand:DI 2 "ior_operand" "M,i")))]
+               (match_operand:DI 2 "cint_ior_operand" "M,i")))]
   "TARGET_64BIT"
-  "* return output_64bit_ior (operands); "
+  "* return pa_output_64bit_ior (operands); "
   [(set_attr "type" "binary,shift")
    (set_attr "length" "4,4")])
 
 (define_expand "iorsi3"
   [(set (match_operand:SI 0 "register_operand" "")
        (ior:SI (match_operand:SI 1 "register_operand" "")
-               (match_operand:SI 2 "arith32_operand" "")))]
+               (match_operand:SI 2 "reg_or_cint_ior_operand" "")))]
   ""
-  "
-{
-  if (! (ior_operand (operands[2], SImode)
-         || register_operand (operands[2], SImode)))
-    operands[2] = force_reg (SImode, operands[2]);
-}")
+  "")
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (ior:SI (match_operand:SI 1 "register_operand" "0,0")
-               (match_operand:SI 2 "ior_operand" "M,i")))]
+               (match_operand:SI 2 "cint_ior_operand" "M,i")))]
   ""
-  "* return output_ior (operands); "
+  "* return pa_output_ior (operands); "
   [(set_attr "type" "binary,shift")
    (set_attr "length" "4,4")])
 
   [(set (match_operand:DI 0 "register_operand" "")
        (xor:DI (match_operand:DI 1 "register_operand" "")
                (match_operand:DI 2 "register_operand" "")))]
-  ""
-  "
-{
-}")
-
-(define_insn ""
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (xor:DI (match_operand:DI 1 "register_operand" "%r")
-               (match_operand:DI 2 "register_operand" "r")))]
-  "!TARGET_64BIT"
-  "xor %1,%2,%0\;xor %R1,%R2,%R0"
-  [(set_attr "type" "binary")
-   (set_attr "length" "8")])
+  "TARGET_64BIT"
+  "")
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
 ;; Processors prior to PA 2.0 don't have a fneg instruction.  Fast
 ;; negation can be done by subtracting from plus zero.  However, this
 ;; violates the IEEE standard when negating plus and minus zero.
+;; The slow path toggles the sign bit in the general registers.
 (define_expand "negdf2"
-  [(parallel [(set (match_operand:DF 0 "register_operand" "")
-                  (neg:DF (match_operand:DF 1 "register_operand" "")))
-             (use (match_dup 2))])]
-  "! TARGET_SOFT_FLOAT"
+  [(set (match_operand:DF 0 "register_operand" "")
+       (neg:DF (match_operand:DF 1 "register_operand" "")))]
+  "!TARGET_SOFT_FLOAT"
 {
-  if (TARGET_PA_20 || flag_unsafe_math_optimizations)
+  if (TARGET_PA_20 || !flag_signed_zeros)
     emit_insn (gen_negdf2_fast (operands[0], operands[1]));
   else
-    {
-      operands[2] = force_reg (DFmode,
-       CONST_DOUBLE_FROM_REAL_VALUE (dconstm1, DFmode));
-      emit_insn (gen_muldf3 (operands[0], operands[1], operands[2]));
-    }
+    emit_insn (gen_negdf2_slow (operands[0], operands[1]));
   DONE;
 })
 
+(define_insn "negdf2_slow"
+  [(set (match_operand:DF 0 "register_operand" "=r")
+       (neg:DF (match_operand:DF 1 "register_operand" "r")))]
+  "!TARGET_SOFT_FLOAT && !TARGET_PA_20"
+  "*
+{
+  if (rtx_equal_p (operands[0], operands[1]))
+    return \"and,< %1,%1,%0\;depi,tr 1,0,1,%0\;depi 0,0,1,%0\";
+  else
+    return \"and,< %1,%1,%0\;depi,tr 1,0,1,%0\;depi 0,0,1,%0\;copy %R1,%R0\";
+}"
+  [(set_attr "type" "multi")
+   (set (attr "length")
+       (if_then_else (match_test "rtx_equal_p (operands[0], operands[1])")
+           (const_int 12)
+           (const_int 16)))])
+
 (define_insn "negdf2_fast"
   [(set (match_operand:DF 0 "register_operand" "=f")
        (neg:DF (match_operand:DF 1 "register_operand" "f")))]
-  "! TARGET_SOFT_FLOAT && (TARGET_PA_20 || flag_unsafe_math_optimizations)"
+  "!TARGET_SOFT_FLOAT"
   "*
 {
   if (TARGET_PA_20)
    (set_attr "length" "4")])
 
 (define_expand "negsf2"
-  [(parallel [(set (match_operand:SF 0 "register_operand" "")
-                  (neg:SF (match_operand:SF 1 "register_operand" "")))
-             (use (match_dup 2))])]
-  "! TARGET_SOFT_FLOAT"
+  [(set (match_operand:SF 0 "register_operand" "")
+       (neg:SF (match_operand:SF 1 "register_operand" "")))]
+  "!TARGET_SOFT_FLOAT"
 {
-  if (TARGET_PA_20 || flag_unsafe_math_optimizations)
+  if (TARGET_PA_20 || !flag_signed_zeros)
     emit_insn (gen_negsf2_fast (operands[0], operands[1]));
   else
-    {
-      operands[2] = force_reg (SFmode,
-       CONST_DOUBLE_FROM_REAL_VALUE (dconstm1, SFmode));
-      emit_insn (gen_mulsf3 (operands[0], operands[1], operands[2]));
-    }
+    emit_insn (gen_negsf2_slow (operands[0], operands[1]));
   DONE;
 })
 
+(define_insn "negsf2_slow"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+       (neg:SF (match_operand:SF 1 "register_operand" "r")))]
+  "!TARGET_SOFT_FLOAT && !TARGET_PA_20"
+  "and,< %1,%1,%0\;depi,tr 1,0,1,%0\;depi 0,0,1,%0"
+  [(set_attr "type" "multi")
+   (set_attr "length" "12")])
+
 (define_insn "negsf2_fast"
   [(set (match_operand:SF 0 "register_operand" "=f")
        (neg:SF (match_operand:SF 1 "register_operand" "f")))]
-  "! TARGET_SOFT_FLOAT && (TARGET_PA_20 || flag_unsafe_math_optimizations)"
+  "!TARGET_SOFT_FLOAT"
   "*
 {
   if (TARGET_PA_20)
 ;; PA 2.0 floating point instructions
 
 ; fmpyfadd patterns
-(define_insn ""
+(define_insn "fmadf4"
   [(set (match_operand:DF 0 "register_operand" "=f")
-       (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "f")
-                         (match_operand:DF 2 "register_operand" "f"))
-                (match_operand:DF 3 "register_operand" "f")))]
+       (fma:DF (match_operand:DF 1 "register_operand" "f")
+               (match_operand:DF 2 "register_operand" "f")
+               (match_operand:DF 3 "register_operand" "f")))]
   "TARGET_PA_20 && ! TARGET_SOFT_FLOAT"
   "fmpyfadd,dbl %1,%2,%3,%0"
   [(set_attr "type" "fpmuldbl")
    (set_attr "length" "4")])
 
-(define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=f")
-       (plus:DF (match_operand:DF 1 "register_operand" "f")
-                (mult:DF (match_operand:DF 2 "register_operand" "f")
-                         (match_operand:DF 3 "register_operand" "f"))))]
-  "TARGET_PA_20 && ! TARGET_SOFT_FLOAT"
-  "fmpyfadd,dbl %2,%3,%1,%0"
-  [(set_attr "type" "fpmuldbl")
-   (set_attr "length" "4")])
-
-(define_insn ""
+(define_insn "fmasf4"
   [(set (match_operand:SF 0 "register_operand" "=f")
-       (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "f")
-                         (match_operand:SF 2 "register_operand" "f"))
-                (match_operand:SF 3 "register_operand" "f")))]
+       (fma:SF (match_operand:SF 1 "register_operand" "f")
+               (match_operand:SF 2 "register_operand" "f")
+               (match_operand:SF 3 "register_operand" "f")))]
   "TARGET_PA_20 && ! TARGET_SOFT_FLOAT"
   "fmpyfadd,sgl %1,%2,%3,%0"
   [(set_attr "type" "fpmulsgl")
    (set_attr "length" "4")])
 
-(define_insn ""
-  [(set (match_operand:SF 0 "register_operand" "=f")
-       (plus:SF (match_operand:SF 1 "register_operand" "f")
-                (mult:SF (match_operand:SF 2 "register_operand" "f")
-                         (match_operand:SF 3 "register_operand" "f"))))]
-  "TARGET_PA_20 && ! TARGET_SOFT_FLOAT"
-  "fmpyfadd,sgl %2,%3,%1,%0"
-  [(set_attr "type" "fpmulsgl")
-   (set_attr "length" "4")])
-
 ; fmpynfadd patterns
-(define_insn ""
+(define_insn "fnmadf4"
   [(set (match_operand:DF 0 "register_operand" "=f")
-       (minus:DF (match_operand:DF 1 "register_operand" "f")
-                 (mult:DF (match_operand:DF 2 "register_operand" "f")
-                          (match_operand:DF 3 "register_operand" "f"))))]
+       (fma:DF (neg:DF (match_operand:DF 1 "register_operand" "f"))
+               (match_operand:DF 2 "register_operand" "f")
+               (match_operand:DF 3 "register_operand" "f")))]
   "TARGET_PA_20 && ! TARGET_SOFT_FLOAT"
-  "fmpynfadd,dbl %2,%3,%1,%0"
+  "fmpynfadd,dbl %1,%2,%3,%0"
   [(set_attr "type" "fpmuldbl")
    (set_attr "length" "4")])
 
-(define_insn ""
+(define_insn "fnmasf4"
   [(set (match_operand:SF 0 "register_operand" "=f")
-       (minus:SF (match_operand:SF 1 "register_operand" "f")
-                 (mult:SF (match_operand:SF 2 "register_operand" "f")
-                          (match_operand:SF 3 "register_operand" "f"))))]
+       (fma:SF (neg:SF (match_operand:SF 1 "register_operand" "f"))
+               (match_operand:SF 2 "register_operand" "f")
+               (match_operand:SF 3 "register_operand" "f")))]
   "TARGET_PA_20 && ! TARGET_SOFT_FLOAT"
-  "fmpynfadd,sgl %2,%3,%1,%0"
+  "fmpynfadd,sgl %1,%2,%3,%0"
   [(set_attr "type" "fpmulsgl")
    (set_attr "length" "4")])
 
   [(set_attr "type" "fpalu")
    (set_attr "length" "4")])
 
-;; Generating a fused multiply sequence is a win for this case as it will
-;; reduce the latency for the fused case without impacting the plain
-;; multiply case.
-;;
-;; Similar possibilities exist for fnegabs, shadd and other insns which
-;; perform two operations with the result of the first feeding the second.
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
-       (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "f")
-                         (match_operand:DF 2 "register_operand" "f"))
-                (match_operand:DF 3 "register_operand" "f")))
-   (set (match_operand:DF 4 "register_operand" "=&f")
-       (mult:DF (match_dup 1) (match_dup 2)))]
+       (neg:DF (abs:DF (match_operand:DF 1 "register_operand" "f"))))
+   (set (match_operand:DF 2 "register_operand" "=&f") (abs:DF (match_dup 1)))]
   "(! TARGET_SOFT_FLOAT && TARGET_PA_20
-    && ! (reg_overlap_mentioned_p (operands[4], operands[1])
-          || reg_overlap_mentioned_p (operands[4], operands[2])))"
+    && ! reg_overlap_mentioned_p (operands[2], operands[1]))"
   "#"
-  [(set_attr "type" "fpmuldbl")
+  [(set_attr "type" "fpalu")
    (set_attr "length" "8")])
 
-;; We want to split this up during scheduling since we want both insns
-;; to schedule independently.
 (define_split
   [(set (match_operand:DF 0 "register_operand" "")
-       (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "")
-                         (match_operand:DF 2 "register_operand" ""))
-                (match_operand:DF 3 "register_operand" "")))
-   (set (match_operand:DF 4 "register_operand" "")
-       (mult:DF (match_dup 1) (match_dup 2)))]
+       (neg:DF (abs:DF (match_operand:DF 1 "register_operand" ""))))
+   (set (match_operand:DF 2 "register_operand" "") (abs:DF (match_dup 1)))]
   "! TARGET_SOFT_FLOAT && TARGET_PA_20"
-  [(set (match_dup 4) (mult:DF (match_dup 1) (match_dup 2)))
-   (set (match_dup 0) (plus:DF (mult:DF (match_dup 1) (match_dup 2))
-                              (match_dup 3)))]
+  [(set (match_dup 2) (abs:DF (match_dup 1)))
+   (set (match_dup 0) (neg:DF (abs:DF (match_dup 1))))]
   "")
 
 (define_insn ""
   [(set (match_operand:SF 0 "register_operand" "=f")
-       (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "f")
-                         (match_operand:SF 2 "register_operand" "f"))
-                (match_operand:SF 3 "register_operand" "f")))
-   (set (match_operand:SF 4 "register_operand" "=&f")
-       (mult:SF (match_dup 1) (match_dup 2)))]
+       (neg:SF (abs:SF (match_operand:SF 1 "register_operand" "f"))))
+   (set (match_operand:SF 2 "register_operand" "=&f") (abs:SF (match_dup 1)))]
   "(! TARGET_SOFT_FLOAT && TARGET_PA_20
-    && ! (reg_overlap_mentioned_p (operands[4], operands[1])
-          || reg_overlap_mentioned_p (operands[4], operands[2])))"
+    && ! reg_overlap_mentioned_p (operands[2], operands[1]))"
   "#"
-  [(set_attr "type" "fpmuldbl")
+  [(set_attr "type" "fpalu")
    (set_attr "length" "8")])
 
-;; We want to split this up during scheduling since we want both insns
-;; to schedule independently.
 (define_split
   [(set (match_operand:SF 0 "register_operand" "")
-       (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "")
-                         (match_operand:SF 2 "register_operand" ""))
-                (match_operand:SF 3 "register_operand" "")))
-   (set (match_operand:SF 4 "register_operand" "")
-       (mult:SF (match_dup 1) (match_dup 2)))]
+       (neg:SF (abs:SF (match_operand:SF 1 "register_operand" ""))))
+   (set (match_operand:SF 2 "register_operand" "") (abs:SF (match_dup 1)))]
   "! TARGET_SOFT_FLOAT && TARGET_PA_20"
-  [(set (match_dup 4) (mult:SF (match_dup 1) (match_dup 2)))
-   (set (match_dup 0) (plus:SF (mult:SF (match_dup 1) (match_dup 2))
-                              (match_dup 3)))]
+  [(set (match_dup 2) (abs:SF (match_dup 1)))
+   (set (match_dup 0) (neg:SF (abs:SF (match_dup 1))))]
   "")
 
 ;; Negating a multiply can be faked by adding zero in a fused multiply-add
-;; instruction.
+;; instruction if we can ignore the sign of zero.
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
        (neg:DF (mult:DF (match_operand:DF 1 "register_operand" "f")
                         (match_operand:DF 2 "register_operand" "f"))))]
-  "! TARGET_SOFT_FLOAT && TARGET_PA_20"
+  "!TARGET_SOFT_FLOAT && TARGET_PA_20 && !flag_signed_zeros"
   "fmpynfadd,dbl %1,%2,%%fr0,%0"
   [(set_attr "type" "fpmuldbl")
    (set_attr "length" "4")])
   [(set (match_operand:SF 0 "register_operand" "=f")
        (neg:SF (mult:SF (match_operand:SF 1 "register_operand" "f")
                         (match_operand:SF 2 "register_operand" "f"))))]
-  "! TARGET_SOFT_FLOAT && TARGET_PA_20"
+  "!TARGET_SOFT_FLOAT && TARGET_PA_20 && !flag_signed_zeros"
   "fmpynfadd,sgl %1,%2,%%fr0,%0"
   [(set_attr "type" "fpmuldbl")
    (set_attr "length" "4")])
                         (match_operand:DF 2 "register_operand" "f"))))
    (set (match_operand:DF 3 "register_operand" "=&f")
        (mult:DF (match_dup 1) (match_dup 2)))]
-  "(! TARGET_SOFT_FLOAT && TARGET_PA_20
+  "(!TARGET_SOFT_FLOAT && TARGET_PA_20 && !flag_signed_zeros
     && ! (reg_overlap_mentioned_p (operands[3], operands[1])
           || reg_overlap_mentioned_p (operands[3], operands[2])))"
   "#"
                         (match_operand:DF 2 "register_operand" ""))))
    (set (match_operand:DF 3 "register_operand" "")
        (mult:DF (match_dup 1) (match_dup 2)))]
-  "! TARGET_SOFT_FLOAT && TARGET_PA_20"
+  "!TARGET_SOFT_FLOAT && TARGET_PA_20 && !flag_signed_zeros"
   [(set (match_dup 3) (mult:DF (match_dup 1) (match_dup 2)))
    (set (match_dup 0) (neg:DF (mult:DF (match_dup 1) (match_dup 2))))]
   "")
                         (match_operand:SF 2 "register_operand" "f"))))
    (set (match_operand:SF 3 "register_operand" "=&f")
        (mult:SF (match_dup 1) (match_dup 2)))]
-  "(! TARGET_SOFT_FLOAT && TARGET_PA_20
+  "(!TARGET_SOFT_FLOAT && TARGET_PA_20 && !flag_signed_zeros
     && ! (reg_overlap_mentioned_p (operands[3], operands[1])
           || reg_overlap_mentioned_p (operands[3], operands[2])))"
   "#"
                         (match_operand:SF 2 "register_operand" ""))))
    (set (match_operand:SF 3 "register_operand" "")
        (mult:SF (match_dup 1) (match_dup 2)))]
-  "! TARGET_SOFT_FLOAT && TARGET_PA_20"
+  "!TARGET_SOFT_FLOAT && TARGET_PA_20&& !flag_signed_zeros"
   [(set (match_dup 3) (mult:SF (match_dup 1) (match_dup 2)))
    (set (match_dup 0) (neg:SF (mult:SF (match_dup 1) (match_dup 2))))]
   "")
-
-;; Now fused multiplies with the result of the multiply negated.
-(define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=f")
-       (plus:DF (neg:DF (mult:DF (match_operand:DF 1 "register_operand" "f")
-                                 (match_operand:DF 2 "register_operand" "f")))
-                (match_operand:DF 3 "register_operand" "f")))]
-  "! TARGET_SOFT_FLOAT && TARGET_PA_20"
-  "fmpynfadd,dbl %1,%2,%3,%0"
-  [(set_attr "type" "fpmuldbl")
-   (set_attr "length" "4")])
-
-(define_insn ""
-  [(set (match_operand:SF 0 "register_operand" "=f")
-       (plus:SF (neg:SF (mult:SF (match_operand:SF 1 "register_operand" "f")
-                        (match_operand:SF 2 "register_operand" "f")))
-                (match_operand:SF 3 "register_operand" "f")))]
-  "! TARGET_SOFT_FLOAT && TARGET_PA_20"
-  "fmpynfadd,sgl %1,%2,%3,%0"
-  [(set_attr "type" "fpmuldbl")
-   (set_attr "length" "4")])
-
-(define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=f")
-       (plus:DF (neg:DF (mult:DF (match_operand:DF 1 "register_operand" "f")
-                                 (match_operand:DF 2 "register_operand" "f")))
-                (match_operand:DF 3 "register_operand" "f")))
-   (set (match_operand:DF 4 "register_operand" "=&f")
-       (mult:DF (match_dup 1) (match_dup 2)))]
-  "(! TARGET_SOFT_FLOAT && TARGET_PA_20
-    && ! (reg_overlap_mentioned_p (operands[4], operands[1])
-          || reg_overlap_mentioned_p (operands[4], operands[2])))"
-  "#"
-  [(set_attr "type" "fpmuldbl")
-   (set_attr "length" "8")])
-
-(define_split
-  [(set (match_operand:DF 0 "register_operand" "")
-       (plus:DF (neg:DF (mult:DF (match_operand:DF 1 "register_operand" "")
-                                 (match_operand:DF 2 "register_operand" "")))
-                (match_operand:DF 3 "register_operand" "")))
-   (set (match_operand:DF 4 "register_operand" "")
-       (mult:DF (match_dup 1) (match_dup 2)))]
-  "! TARGET_SOFT_FLOAT && TARGET_PA_20"
-  [(set (match_dup 4) (mult:DF (match_dup 1) (match_dup 2)))
-   (set (match_dup 0) (plus:DF (neg:DF (mult:DF (match_dup 1) (match_dup 2)))
-                              (match_dup 3)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:SF 0 "register_operand" "=f")
-       (plus:SF (neg:SF (mult:SF (match_operand:SF 1 "register_operand" "f")
-                                 (match_operand:SF 2 "register_operand" "f")))
-                (match_operand:SF 3 "register_operand" "f")))
-   (set (match_operand:SF 4 "register_operand" "=&f")
-       (mult:SF (match_dup 1) (match_dup 2)))]
-  "(! TARGET_SOFT_FLOAT && TARGET_PA_20
-    && ! (reg_overlap_mentioned_p (operands[4], operands[1])
-          || reg_overlap_mentioned_p (operands[4], operands[2])))"
-  "#"
-  [(set_attr "type" "fpmuldbl")
-   (set_attr "length" "8")])
-
-(define_split
-  [(set (match_operand:SF 0 "register_operand" "")
-       (plus:SF (neg:SF (mult:SF (match_operand:SF 1 "register_operand" "")
-                                 (match_operand:SF 2 "register_operand" "")))
-                (match_operand:SF 3 "register_operand" "")))
-   (set (match_operand:SF 4 "register_operand" "")
-       (mult:SF (match_dup 1) (match_dup 2)))]
-  "! TARGET_SOFT_FLOAT && TARGET_PA_20"
-  [(set (match_dup 4) (mult:SF (match_dup 1) (match_dup 2)))
-   (set (match_dup 0) (plus:SF (neg:SF (mult:SF (match_dup 1) (match_dup 2)))
-                              (match_dup 3)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=f")
-       (minus:DF (match_operand:DF 3 "register_operand" "f")
-                 (mult:DF (match_operand:DF 1 "register_operand" "f")
-                          (match_operand:DF 2 "register_operand" "f"))))
-   (set (match_operand:DF 4 "register_operand" "=&f")
-       (mult:DF (match_dup 1) (match_dup 2)))]
-  "(! TARGET_SOFT_FLOAT && TARGET_PA_20
-    && ! (reg_overlap_mentioned_p (operands[4], operands[1])
-          || reg_overlap_mentioned_p (operands[4], operands[2])))"
-  "#"
-  [(set_attr "type" "fpmuldbl")
-   (set_attr "length" "8")])
-
-(define_split
-  [(set (match_operand:DF 0 "register_operand" "")
-       (minus:DF (match_operand:DF 3 "register_operand" "")
-                 (mult:DF (match_operand:DF 1 "register_operand" "")
-                          (match_operand:DF 2 "register_operand" ""))))
-   (set (match_operand:DF 4 "register_operand" "")
-       (mult:DF (match_dup 1) (match_dup 2)))]
-  "! TARGET_SOFT_FLOAT && TARGET_PA_20"
-  [(set (match_dup 4) (mult:DF (match_dup 1) (match_dup 2)))
-   (set (match_dup 0) (minus:DF (match_dup 3)
-                               (mult:DF (match_dup 1) (match_dup 2))))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:SF 0 "register_operand" "=f")
-       (minus:SF (match_operand:SF 3 "register_operand" "f")
-                 (mult:SF (match_operand:SF 1 "register_operand" "f")
-                          (match_operand:SF 2 "register_operand" "f"))))
-   (set (match_operand:SF 4 "register_operand" "=&f")
-       (mult:SF (match_dup 1) (match_dup 2)))]
-  "(! TARGET_SOFT_FLOAT && TARGET_PA_20
-    && ! (reg_overlap_mentioned_p (operands[4], operands[1])
-          || reg_overlap_mentioned_p (operands[4], operands[2])))"
-  "#"
-  [(set_attr "type" "fpmuldbl")
-   (set_attr "length" "8")])
-
-(define_split
-  [(set (match_operand:SF 0 "register_operand" "")
-       (minus:SF (match_operand:SF 3 "register_operand" "")
-                 (mult:SF (match_operand:SF 1 "register_operand" "")
-                          (match_operand:SF 2 "register_operand" ""))))
-   (set (match_operand:SF 4 "register_operand" "")
-       (mult:SF (match_dup 1) (match_dup 2)))]
-  "! TARGET_SOFT_FLOAT && TARGET_PA_20"
-  [(set (match_dup 4) (mult:SF (match_dup 1) (match_dup 2)))
-   (set (match_dup 0) (minus:SF (match_dup 3)
-                               (mult:SF (match_dup 1) (match_dup 2))))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=f")
-       (neg:DF (abs:DF (match_operand:DF 1 "register_operand" "f"))))
-   (set (match_operand:DF 2 "register_operand" "=&f") (abs:DF (match_dup 1)))]
-  "(! TARGET_SOFT_FLOAT && TARGET_PA_20
-    && ! reg_overlap_mentioned_p (operands[2], operands[1]))"
-  "#"
-  [(set_attr "type" "fpalu")
-   (set_attr "length" "8")])
-
-(define_split
-  [(set (match_operand:DF 0 "register_operand" "")
-       (neg:DF (abs:DF (match_operand:DF 1 "register_operand" ""))))
-   (set (match_operand:DF 2 "register_operand" "") (abs:DF (match_dup 1)))]
-  "! TARGET_SOFT_FLOAT && TARGET_PA_20"
-  [(set (match_dup 2) (abs:DF (match_dup 1)))
-   (set (match_dup 0) (neg:DF (abs:DF (match_dup 1))))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:SF 0 "register_operand" "=f")
-       (neg:SF (abs:SF (match_operand:SF 1 "register_operand" "f"))))
-   (set (match_operand:SF 2 "register_operand" "=&f") (abs:SF (match_dup 1)))]
-  "(! TARGET_SOFT_FLOAT && TARGET_PA_20
-    && ! reg_overlap_mentioned_p (operands[2], operands[1]))"
-  "#"
-  [(set_attr "type" "fpalu")
-   (set_attr "length" "8")])
-
-(define_split
-  [(set (match_operand:SF 0 "register_operand" "")
-       (neg:SF (abs:SF (match_operand:SF 1 "register_operand" ""))))
-   (set (match_operand:SF 2 "register_operand" "") (abs:SF (match_dup 1)))]
-  "! TARGET_SOFT_FLOAT && TARGET_PA_20"
-  [(set (match_dup 2) (abs:SF (match_dup 1)))
-   (set (match_dup 0) (neg:SF (abs:SF (match_dup 1))))]
-  "")
 \f
 ;;- Shift instructions
 
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (plus:SI (ashift:SI (match_operand:SI 2 "register_operand" "r")
+                           (match_operand:SI 3 "shadd_operand" ""))
+                (match_operand:SI 1 "register_operand" "r")))]
+  ""
+  "{sh%o3addl %2,%1,%0|shladd,l %2,%o3,%1,%0} "
+  [(set_attr "type" "binary")
+   (set_attr "length" "4")])
+
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
        (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "r")
-                         (match_operand:SI 3 "shadd_operand" ""))
+                         (match_operand:SI 3 "mem_shadd_operand" ""))
                 (match_operand:SI 1 "register_operand" "r")))]
   ""
-  "{sh%O3addl %2,%1,%0|shladd,l %2,%O3,%1,%0} "
+  "*
+{
+  int shift_val = exact_log2 (INTVAL (operands[3]));
+  operands[3] = GEN_INT (shift_val);
+  return \"{sh%o3addl %2,%1,%0|shladd,l %2,%o3,%1,%0}\";
+}"
+  [(set_attr "type" "binary")
+   (set_attr "length" "4")])
+
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (plus:DI (ashift:DI (match_operand:DI 2 "register_operand" "r")
+                           (match_operand:DI 3 "shadd_operand" ""))
+                (match_operand:DI 1 "register_operand" "r")))]
+  "TARGET_64BIT"
+  "shladd,l %2,%o3,%1,%0"
   [(set_attr "type" "binary")
    (set_attr "length" "4")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
        (plus:DI (mult:DI (match_operand:DI 2 "register_operand" "r")
-                         (match_operand:DI 3 "shadd_operand" ""))
+                         (match_operand:DI 3 "mem_shadd_operand" ""))
                 (match_operand:DI 1 "register_operand" "r")))]
   "TARGET_64BIT"
-  "shladd,l %2,%O3,%1,%0"
+  "*
+{
+  int shift_val = exact_log2 (INTVAL (operands[3]));
+  operands[3] = GEN_INT (shift_val);
+  return \"shladd,l %2,%o3,%1,%0\";
+}"
   [(set_attr "type" "binary")
    (set_attr "length" "4")])
 
   ""
   "*
 {
-  int x = INTVAL (operands[1]);
+  unsigned HOST_WIDE_INT x = UINTVAL (operands[1]);
   operands[2] = GEN_INT (4 + exact_log2 ((x >> 4) + 1));
   operands[1] = GEN_INT ((x & 0xf) - 0x10);
   return \"{zvdepi %1,%2,%0|depwi,z %1,%%sar,%2,%0}\";
   "exact_log2 (INTVAL (operands[1]) + 1) > 0"
   "*
 {
-  int x = INTVAL (operands[1]);
+  HOST_WIDE_INT x = INTVAL (operands[1]);
   operands[2] = GEN_INT (exact_log2 (x + 1));
   return \"{vdepi -1,%2,%0|depwi -1,%%sar,%2,%0}\";
 }"
   "INTVAL (operands[1]) == -2"
   "*
 {
-  int x = INTVAL (operands[1]);
+  HOST_WIDE_INT x = INTVAL (operands[1]);
   operands[2] = GEN_INT (exact_log2 ((~x) + 1));
   return \"{vdepi 0,%2,%0|depwi 0,%%sar,%2,%0}\";
 }"
   "TARGET_64BIT"
   "*
 {
-  int x = INTVAL (operands[1]);
+  unsigned HOST_WIDE_INT x = UINTVAL (operands[1]);
   operands[2] = GEN_INT (4 + exact_log2 ((x >> 4) + 1));
   operands[1] = GEN_INT ((x & 0x1f) - 0x20);
   return \"depdi,z %1,%%sar,%2,%0\";
   "TARGET_64BIT && exact_log2 (INTVAL (operands[1]) + 1) > 0"
   "*
 {
-  int x = INTVAL (operands[1]);
+  HOST_WIDE_INT x = INTVAL (operands[1]);
   operands[2] = GEN_INT (exact_log2 (x + 1));
   return \"depdi -1,%%sar,%2,%0\";
 }"
   "TARGET_64BIT && INTVAL (operands[1]) == -2"
   "*
 {
-  int x = INTVAL (operands[1]);
+  HOST_WIDE_INT x = INTVAL (operands[1]);
   operands[2] = GEN_INT (exact_log2 ((~x) + 1));
   return \"depdi 0,%%sar,%2,%0\";
 }"
 (define_insn "lshrsi3"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
-                    (match_operand:SI 2 "arith32_operand" "q,n")))]
+                    (match_operand:SI 2 "shift5_operand" "q,n")))]
   ""
   "@
    {vshd %%r0,%1,%0|shrpw %%r0,%1,%%sar,%0}
 (define_insn "lshrdi3"
   [(set (match_operand:DI 0 "register_operand" "=r,r")
        (lshiftrt:DI (match_operand:DI 1 "register_operand" "r,r")
-                    (match_operand:DI 2 "arith32_operand" "q,n")))]
+                    (match_operand:DI 2 "shift6_operand" "q,n")))]
   "TARGET_64BIT"
   "@
    shrpd %%r0,%1,%%sar,%0
   [(set_attr "type" "shift")
    (set_attr "length" "4")])
 
+; Shift right pair word 0 to 31 bits.
+(define_insn "shrpsi4"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r,r")
+                          (minus:SI (const_int 32)
+                            (match_operand:SI 3 "shift5_operand" "q,n")))
+               (lshiftrt:SI (match_operand:SI 2 "register_operand" "r,r")
+                            (match_dup 3))))]
+  ""
+  "@
+   {vshd %1,%2,%0|shrpw %1,%2,%%sar,%0}
+   {shd|shrpw} %1,%2,%3,%0"
+  [(set_attr "type" "shift")
+   (set_attr "length" "4")])
+
+; Shift right pair doubleword 0 to 63 bits.
+(define_insn "shrpdi4"
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (ior:DI (ashift:DI (match_operand:SI 1 "register_operand" "r,r")
+                          (minus:DI (const_int 64)
+                            (match_operand:DI 3 "shift6_operand" "q,n")))
+               (lshiftrt:DI (match_operand:DI 2 "register_operand" "r,r")
+                            (match_dup 3))))]
+  "TARGET_64BIT"
+  "@
+   shrpd %1,%2,%%sar,%0
+   shrpd %1,%2,%3,%0"
+  [(set_attr "type" "shift")
+   (set_attr "length" "4")])
+
 (define_insn "rotrsi3"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (rotatert:SI (match_operand:SI 1 "register_operand" "r,r")
-                    (match_operand:SI 2 "arith32_operand" "q,n")))]
+                    (match_operand:SI 2 "shift5_operand" "q,n")))]
   ""
   "*
 {
 \f
 ;; Unconditional and other jump instructions.
 
+;; Trivial return used when no epilogue is needed.
+(define_insn "return"
+  [(return)
+   (use (reg:SI 2))]
+  "pa_can_use_return_insn ()"
+  "*
+{
+  if (TARGET_PA_20)
+    return \"bve%* (%%r2)\";
+  return \"bv%* %%r0(%%r2)\";
+}"
+  [(set_attr "type" "branch")
+   (set_attr "length" "4")])
+
 ;; This is used for most returns.
 (define_insn "return_internal"
   [(return)
 (define_expand "prologue"
   [(const_int 0)]
   ""
-  "hppa_expand_prologue ();DONE;")
+  "pa_expand_prologue ();DONE;")
 
 (define_expand "sibcall_epilogue"
   [(return)]
   ""
   "
 {
-  hppa_expand_epilogue ();
+  pa_expand_epilogue ();
   DONE;
 }")
 
   rtx x;
 
   /* Try to use the trivial return first.  Else use the full epilogue.  */
-  if (reload_completed
-      && !frame_pointer_needed
-      && !df_regs_ever_live_p (2)
-      && (compute_frame_size (get_frame_size (), 0) ? 0 : 1))
-    x = gen_return_internal ();
+  if (pa_can_use_return_insn ())
+    x = gen_return ();
   else
     {
-      hppa_expand_epilogue ();
+      pa_expand_epilogue ();
 
       /* EH returns bypass the normal return stub.  Thus, we must do an
         interspace branch to return from functions that call eh_return.
   if (get_attr_length (insn) < 16)
     return \"b%* %l0\";
 
-  return output_lbranch (operands[0], insn, 1);
+  return pa_output_lbranch (operands[0], insn, 1);
 }"
   [(set_attr "type" "uncond_branch")
    (set_attr "pa_combine_type" "uncond_branch")
    (set (attr "length")
-    (cond [(eq (symbol_ref "jump_in_call_delay (insn)") (const_int 1))
-          (if_then_else (lt (abs (minus (match_dup 0)
-                                        (plus (pc) (const_int 8))))
-                            (const_int MAX_12BIT_OFFSET))
-          (const_int 4)
-          (const_int 8))
-          (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
+    (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 4)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 20)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 16)]
          (const_int 24)))])
 
 ;;; Hope this is only within a function...
 (define_insn "indirect_jump"
-  [(set (pc) (match_operand 0 "register_operand" "r"))]
-  "GET_MODE (operands[0]) == word_mode"
+  [(set (pc) (match_operand 0 "pmode_register_operand" "r"))]
+  ""
   "bv%* %%r0(%0)"
   [(set_attr "type" "branch")
    (set_attr "length" "4")])
   rtx stack = operands[2];
   rtx fp = operands[3];
 
-  lab = copy_to_reg (lab);
-
   emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
   emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
 
-  /* Restore the frame pointer.  The virtual_stack_vars_rtx is saved
-     instead of the hard_frame_pointer_rtx in the save area.  As a
-     result, an extra instruction is needed to adjust for the offset
-     of the virtual stack variables and the frame pointer.  */
-  if (GET_CODE (fp) != REG)
-    fp = force_reg (Pmode, fp);
-  emit_move_insn (virtual_stack_vars_rtx, fp);
+  lab = copy_to_reg (lab);
+
+  /* Restore the stack and frame pointers.  */
+  fp = copy_to_reg (fp);
+  emit_stack_restore (SAVE_NONLOCAL, stack);
 
-  emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
+  /* Ensure the frame pointer move is not optimized.  */
+  emit_insn (gen_blockage ());
+  emit_clobber (hard_frame_pointer_rtx);
+  emit_clobber (frame_pointer_rtx);
+  emit_move_insn (hard_frame_pointer_rtx, fp);
 
   emit_use (hard_frame_pointer_rtx);
   emit_use (stack_pointer_rtx);
   [(set_attr "type" "branch")
    (set_attr "length" "4")])
 
-;;; This jump is used in branch tables where the insn length is fixed.
-;;; The length of this insn is adjusted if the delay slot is not filled.
-(define_insn "short_jump"
-  [(set (pc) (label_ref (match_operand 0 "" "")))
-   (const_int 0)]
-  ""
-  "b%* %l0%#"
-  [(set_attr "type" "btable_branch")
-   (set_attr "length" "4")])
-
 ;; Subroutines of "casesi".
 ;; operand 0 is index
 ;; operand 1 is the minimum bound
     {
       rtx index = gen_reg_rtx (SImode);
 
-      operands[1] = GEN_INT (-INTVAL (operands[1]));
+      operands[1] = gen_int_mode (-INTVAL (operands[1]), SImode);
       if (!INT_14_BITS (operands[1]))
        operands[1] = force_reg (SImode, operands[1]);
       emit_insn (gen_addsi3 (index, operands[0], operands[1]));
       operands[0] = index;
     }
 
-  if (TARGET_BIG_SWITCH)
-    {
-      if (TARGET_64BIT)
-       emit_jump_insn (gen_casesi64p (operands[0], operands[3]));
-      else if (flag_pic)
-       emit_jump_insn (gen_casesi32p (operands[0], operands[3]));
-      else
-       emit_jump_insn (gen_casesi32 (operands[0], operands[3]));
-    }
+  if (TARGET_64BIT)
+    emit_jump_insn (gen_casesi64p (operands[0], operands[3]));
+  else if (flag_pic)
+    emit_jump_insn (gen_casesi32p (operands[0], operands[3]));
   else
-    emit_jump_insn (gen_casesi0 (operands[0], operands[3]));
+    emit_jump_insn (gen_casesi32 (operands[0], operands[3]));
   DONE;
 }")
 
-;;; The rtl for this pattern doesn't accurately describe what the insn
-;;; actually does, particularly when case-vector elements are exploded
-;;; in pa_reorg.  However, the initial SET in these patterns must show
-;;; the connection of the insn to the following jump table.
-(define_insn "casesi0"
-  [(set (pc) (mem:SI (plus:SI
-                      (mult:SI (match_operand:SI 0 "register_operand" "r")
-                               (const_int 4))
-                      (label_ref (match_operand 1 "" "")))))]
-  ""
-  "blr,n %0,%%r0\;nop"
-  [(set_attr "type" "multi")
-   (set_attr "length" "8")])
-
 ;;; 32-bit code, absolute branch table.
 (define_insn "casesi32"
   [(set (pc) (mem:SI (plus:SI
 {ldwx|ldw},s %0(%2),%3\;{addl|add,l} %2,%3,%3\;bv,n %%r0(%3)"
   [(set_attr "type" "multi")
    (set (attr "length")
-     (if_then_else (ne (symbol_ref "TARGET_PA_20") (const_int 0))
+     (if_then_else (match_test "TARGET_PA_20")
        (const_int 20)
        (const_int 24)))])
 
@@ -7231,13 +7059,23 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   ""
   "
 {
-  rtx op, call_insn;
+  rtx op;
   rtx nb = operands[1];
 
   if (TARGET_PORTABLE_RUNTIME)
     op = force_reg (SImode, XEXP (operands[0], 0));
   else
-    op = XEXP (operands[0], 0);
+    {
+      op = XEXP (operands[0], 0);
+
+      /* Generate indirect long calls to non-local functions. */
+      if (TARGET_LONG_CALLS && GET_CODE (op) == SYMBOL_REF)
+       {
+         tree call_decl = SYMBOL_REF_DECL (op);
+         if (!(call_decl && targetm.binds_local_p (call_decl)))
+           op = force_reg (word_mode, op);
+       }
+    }
 
   if (TARGET_64BIT)
     {
@@ -7296,11 +7134,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
     {
       rtx r4 = gen_rtx_REG (word_mode, 4);
       if (GET_CODE (op) == SYMBOL_REF)
-       call_insn = emit_call_insn (gen_call_symref_64bit (op, nb, r4));
+       emit_call_insn (gen_call_symref_64bit (op, nb, r4));
       else
        {
          op = force_reg (word_mode, op);
-         call_insn = emit_call_insn (gen_call_reg_64bit (op, nb, r4));
+         emit_call_insn (gen_call_reg_64bit (op, nb, r4));
        }
     }
   else
@@ -7310,10 +7148,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
          if (flag_pic)
            {
              rtx r4 = gen_rtx_REG (word_mode, 4);
-             call_insn = emit_call_insn (gen_call_symref_pic (op, nb, r4));
+             emit_call_insn (gen_call_symref_pic (op, nb, r4));
            }
          else
-           call_insn = emit_call_insn (gen_call_symref (op, nb));
+           emit_call_insn (gen_call_symref (op, nb));
        }
       else
        {
@@ -7322,10 +7160,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
          if (flag_pic)
            {
              rtx r4 = gen_rtx_REG (word_mode, 4);
-             call_insn = emit_call_insn (gen_call_reg_pic (nb, r4));
+             emit_call_insn (gen_call_reg_pic (nb, r4));
            }
          else
-           call_insn = emit_call_insn (gen_call_reg (nb));
+           emit_call_insn (gen_call_reg (nb));
        }
     }
 
@@ -7371,19 +7209,20 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
   "*
 {
-  output_arg_descriptor (insn);
-  return output_call (insn, operands[0], 0);
+  pa_output_arg_descriptor (insn);
+  return pa_output_call (insn, operands[0], 0);
 }"
   [(set_attr "type" "call")
-   (set (attr "length") (symbol_ref "attr_length_call (insn, 0)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_call (insn, 0)")))])
 
 (define_insn "call_symref_pic"
-  [(set (match_operand:SI 2 "register_operand" "=&r") (reg:SI 19))
-   (call (mem:SI (match_operand 0 "call_operand_address" ""))
+  [(call (mem:SI (match_operand 0 "call_operand_address" ""))
         (match_operand 1 "" "i"))
    (clobber (reg:SI 1))
    (clobber (reg:SI 2))
-   (use (match_dup 2))
+   (clobber (match_operand 2))
    (use (reg:SI 19))
    (use (const_int 0))]
   "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
@@ -7399,12 +7238,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 ;; terminate the basic block.  The split has to contain more than one
 ;; insn.
 (define_split
-  [(parallel [(set (match_operand:SI 2 "register_operand" "") (reg:SI 19))
-             (call (mem:SI (match_operand 0 "call_operand_address" ""))
+  [(parallel [(call (mem:SI (match_operand 0 "call_operand_address" ""))
                    (match_operand 1 "" ""))
              (clobber (reg:SI 1))
              (clobber (reg:SI 2))
-             (use (match_dup 2))
+             (clobber (match_operand 2))
              (use (reg:SI 19))
              (use (const_int 0))])]
   "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed
@@ -7419,12 +7257,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "")
 
 (define_split
-  [(parallel [(set (match_operand:SI 2 "register_operand" "") (reg:SI 19))
-             (call (mem:SI (match_operand 0 "call_operand_address" ""))
+  [(parallel [(call (mem:SI (match_operand 0 "call_operand_address" ""))
                    (match_operand 1 "" ""))
              (clobber (reg:SI 1))
              (clobber (reg:SI 2))
-             (use (match_dup 2))
+             (clobber (match_operand 2))
              (use (reg:SI 19))
              (use (const_int 0))])]
   "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed"
@@ -7448,21 +7285,22 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
   "*
 {
-  output_arg_descriptor (insn);
-  return output_call (insn, operands[0], 0);
+  pa_output_arg_descriptor (insn);
+  return pa_output_call (insn, operands[0], 0);
 }"
   [(set_attr "type" "call")
-   (set (attr "length") (symbol_ref "attr_length_call (insn, 0)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_call (insn, 0)")))])
 
 ;; This pattern is split if it is necessary to save and restore the
 ;; PIC register.
 (define_insn "call_symref_64bit"
-  [(set (match_operand:DI 2 "register_operand" "=&r") (reg:DI 27))
-   (call (mem:SI (match_operand 0 "call_operand_address" ""))
+  [(call (mem:SI (match_operand 0 "call_operand_address" ""))
         (match_operand 1 "" "i"))
    (clobber (reg:DI 1))
    (clobber (reg:DI 2))
-   (use (match_dup 2))
+   (clobber (match_operand 2))
    (use (reg:DI 27))
    (use (reg:DI 29))
    (use (const_int 0))]
@@ -7479,12 +7317,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 ;; terminate the basic block.  The split has to contain more than one
 ;; insn.
 (define_split
-  [(parallel [(set (match_operand:DI 2 "register_operand" "") (reg:DI 27))
-             (call (mem:SI (match_operand 0 "call_operand_address" ""))
+  [(parallel [(call (mem:SI (match_operand 0 "call_operand_address" ""))
                    (match_operand 1 "" ""))
              (clobber (reg:DI 1))
              (clobber (reg:DI 2))
-             (use (match_dup 2))
+             (clobber (match_operand 2))
              (use (reg:DI 27))
              (use (reg:DI 29))
              (use (const_int 0))])]
@@ -7501,12 +7338,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "")
 
 (define_split
-  [(parallel [(set (match_operand:DI 2 "register_operand" "") (reg:DI 27))
-             (call (mem:SI (match_operand 0 "call_operand_address" ""))
+  [(parallel [(call (mem:SI (match_operand 0 "call_operand_address" ""))
                    (match_operand 1 "" ""))
              (clobber (reg:DI 1))
              (clobber (reg:DI 2))
-             (use (match_dup 2))
+             (clobber (match_operand 2))
              (use (reg:DI 27))
              (use (reg:DI 29))
              (use (const_int 0))])]
@@ -7533,11 +7369,12 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "TARGET_64BIT"
   "*
 {
-  output_arg_descriptor (insn);
-  return output_call (insn, operands[0], 0);
+  return pa_output_call (insn, operands[0], 0);
 }"
   [(set_attr "type" "call")
-   (set (attr "length") (symbol_ref "attr_length_call (insn, 0)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_call (insn, 0)")))])
 
 (define_insn "call_reg"
   [(call (mem:SI (reg:SI 22))
@@ -7548,20 +7385,21 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "!TARGET_64BIT"
   "*
 {
-  return output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
+  return pa_output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
 }"
   [(set_attr "type" "dyncall")
-   (set (attr "length") (symbol_ref "attr_length_indirect_call (insn)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_indirect_call (insn)")))])
 
 ;; This pattern is split if it is necessary to save and restore the
 ;; PIC register.
 (define_insn "call_reg_pic"
-  [(set (match_operand:SI 1 "register_operand" "=&r") (reg:SI 19))
-   (call (mem:SI (reg:SI 22))
+  [(call (mem:SI (reg:SI 22))
         (match_operand 0 "" "i"))
    (clobber (reg:SI 1))
    (clobber (reg:SI 2))
-   (use (match_dup 1))
+   (clobber (match_operand 1))
    (use (reg:SI 19))
    (use (const_int 1))]
   "!TARGET_64BIT"
@@ -7577,12 +7415,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 ;; terminate the basic block.  The split has to contain more than one
 ;; insn.
 (define_split
-  [(parallel [(set (match_operand:SI 1 "register_operand" "") (reg:SI 19))
-             (call (mem:SI (reg:SI 22))
+  [(parallel [(call (mem:SI (reg:SI 22))
                    (match_operand 0 "" ""))
              (clobber (reg:SI 1))
              (clobber (reg:SI 2))
-             (use (match_dup 1))
+             (clobber (match_operand 1))
              (use (reg:SI 19))
              (use (const_int 1))])]
   "!TARGET_64BIT && reload_completed
@@ -7597,12 +7434,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "")
 
 (define_split
-  [(parallel [(set (match_operand:SI 1 "register_operand" "") (reg:SI 19))
-             (call (mem:SI (reg:SI 22))
+  [(parallel [(call (mem:SI (reg:SI 22))
                    (match_operand 0 "" ""))
              (clobber (reg:SI 1))
              (clobber (reg:SI 2))
-             (use (match_dup 1))
+             (clobber (match_operand 1))
              (use (reg:SI 19))
              (use (const_int 1))])]
   "!TARGET_64BIT && reload_completed"
@@ -7626,20 +7462,20 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "!TARGET_64BIT"
   "*
 {
-  return output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
+  return pa_output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
 }"
   [(set_attr "type" "dyncall")
-   (set (attr "length") (symbol_ref "attr_length_indirect_call (insn)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_indirect_call (insn)")))])
 
 ;; This pattern is split if it is necessary to save and restore the
 ;; PIC register.
 (define_insn "call_reg_64bit"
-  [(set (match_operand:DI 2 "register_operand" "=&r") (reg:DI 27))
-   (call (mem:SI (match_operand:DI 0 "register_operand" "r"))
+  [(call (mem:SI (match_operand:DI 0 "register_operand" "r"))
         (match_operand 1 "" "i"))
-   (clobber (reg:DI 1))
    (clobber (reg:DI 2))
-   (use (match_dup 2))
+   (clobber (match_operand 2))
    (use (reg:DI 27))
    (use (reg:DI 29))
    (use (const_int 1))]
@@ -7656,12 +7492,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 ;; terminate the basic block.  The split has to contain more than one
 ;; insn.
 (define_split
-  [(parallel [(set (match_operand:DI 2 "register_operand" "") (reg:DI 27))
-             (call (mem:SI (match_operand 0 "register_operand" ""))
+  [(parallel [(call (mem:SI (match_operand 0 "register_operand" ""))
                    (match_operand 1 "" ""))
-             (clobber (reg:DI 1))
              (clobber (reg:DI 2))
-             (use (match_dup 2))
+             (clobber (match_operand 2))
              (use (reg:DI 27))
              (use (reg:DI 29))
              (use (const_int 1))])]
@@ -7670,7 +7504,6 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   [(set (match_dup 2) (reg:DI 27))
    (parallel [(call (mem:SI (match_dup 0))
                    (match_dup 1))
-             (clobber (reg:DI 1))
              (clobber (reg:DI 2))
              (use (reg:DI 27))
              (use (reg:DI 29))
@@ -7678,12 +7511,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "")
 
 (define_split
-  [(parallel [(set (match_operand:DI 2 "register_operand" "") (reg:DI 27))
-             (call (mem:SI (match_operand 0 "register_operand" ""))
+  [(parallel [(call (mem:SI (match_operand 0 "register_operand" ""))
                    (match_operand 1 "" ""))
-             (clobber (reg:DI 1))
              (clobber (reg:DI 2))
-             (use (match_dup 2))
+             (clobber (match_operand 2))
              (use (reg:DI 27))
              (use (reg:DI 29))
              (use (const_int 1))])]
@@ -7691,7 +7522,6 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   [(set (match_dup 2) (reg:DI 27))
    (parallel [(call (mem:SI (match_dup 0))
                    (match_dup 1))
-             (clobber (reg:DI 1))
              (clobber (reg:DI 2))
              (use (reg:DI 27))
              (use (reg:DI 29))
@@ -7702,7 +7532,6 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 (define_insn "*call_reg_64bit_post_reload"
   [(call (mem:SI (match_operand:DI 0 "register_operand" "r"))
         (match_operand 1 "" "i"))
-   (clobber (reg:DI 1))
    (clobber (reg:DI 2))
    (use (reg:DI 27))
    (use (reg:DI 29))
@@ -7710,10 +7539,12 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "TARGET_64BIT"
   "*
 {
-  return output_indirect_call (insn, operands[0]);
+  return pa_output_indirect_call (insn, operands[0]);
 }"
   [(set_attr "type" "dyncall")
-   (set (attr "length") (symbol_ref "attr_length_indirect_call (insn)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 12)]
+             (symbol_ref "pa_attr_length_indirect_call (insn)")))])
 
 (define_expand "call_value"
   [(parallel [(set (match_operand 0 "" "")
@@ -7721,16 +7552,33 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
                         (match_operand 2 "" "")))
              (clobber (reg:SI 2))])]
   ""
-  "
 {
-  rtx op, call_insn;
+  rtx op;
   rtx dst = operands[0];
   rtx nb = operands[2];
+  bool call_powf = false;
 
   if (TARGET_PORTABLE_RUNTIME)
     op = force_reg (SImode, XEXP (operands[1], 0));
   else
-    op = XEXP (operands[1], 0);
+    {
+      op = XEXP (operands[1], 0);
+      if (GET_CODE (op) == SYMBOL_REF)
+       {
+         /* Handle special call to buggy powf function.  */
+         if (TARGET_HPUX && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT
+             && !strcmp (targetm.strip_name_encoding (XSTR (op, 0)), "powf"))
+           call_powf = true;
+
+         /* Generate indirect long calls to non-local functions. */
+         else if (TARGET_LONG_CALLS)
+           {
+             tree call_decl = SYMBOL_REF_DECL (op);
+             if (!(call_decl && targetm.binds_local_p (call_decl)))
+               op = force_reg (word_mode, op);
+           }
+       }
+    }
 
   if (TARGET_64BIT)
     {
@@ -7789,13 +7637,16 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
     {
       rtx r4 = gen_rtx_REG (word_mode, 4);
       if (GET_CODE (op) == SYMBOL_REF)
-       call_insn
-         = emit_call_insn (gen_call_val_symref_64bit (dst, op, nb, r4));
+       {
+         if (call_powf)
+           emit_call_insn (gen_call_val_powf_64bit (dst, op, nb, r4));
+         else
+           emit_call_insn (gen_call_val_symref_64bit (dst, op, nb, r4));
+       }
       else
        {
          op = force_reg (word_mode, op);
-         call_insn
-           = emit_call_insn (gen_call_val_reg_64bit (dst, op, nb, r4));
+         emit_call_insn (gen_call_val_reg_64bit (dst, op, nb, r4));
        }
     }
   else
@@ -7805,11 +7656,19 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
          if (flag_pic)
            {
              rtx r4 = gen_rtx_REG (word_mode, 4);
-             call_insn
-               = emit_call_insn (gen_call_val_symref_pic (dst, op, nb, r4));
+
+             if (call_powf)
+               emit_call_insn (gen_call_val_powf_pic (dst, op, nb, r4));
+             else
+               emit_call_insn (gen_call_val_symref_pic (dst, op, nb, r4));
            }
          else
-           call_insn = emit_call_insn (gen_call_val_symref (dst, op, nb));
+           {
+             if (call_powf)
+               emit_call_insn (gen_call_val_powf (dst, op, nb));
+             else
+               emit_call_insn (gen_call_val_symref (dst, op, nb));
+           }
        }
       else
        {
@@ -7818,15 +7677,15 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
          if (flag_pic)
            {
              rtx r4 = gen_rtx_REG (word_mode, 4);
-             call_insn = emit_call_insn (gen_call_val_reg_pic (dst, nb, r4));
+             emit_call_insn (gen_call_val_reg_pic (dst, nb, r4));
            }
          else
-           call_insn = emit_call_insn (gen_call_val_reg (dst, nb));
+           emit_call_insn (gen_call_val_reg (dst, nb));
        }
     }
 
   DONE;
-}")
+})
 
 (define_insn "call_val_symref"
   [(set (match_operand 0 "" "")
@@ -7838,20 +7697,41 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
   "*
 {
-  output_arg_descriptor (insn);
-  return output_call (insn, operands[1], 0);
+  pa_output_arg_descriptor (insn);
+  return pa_output_call (insn, operands[1], 0);
+}"
+  [(set_attr "type" "call")
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_call (insn, 0)")))])
+
+;; powf function clobbers %fr12
+(define_insn "call_val_powf"
+  [(set (match_operand 0 "" "")
+       (call (mem:SI (match_operand 1 "call_operand_address" ""))
+             (match_operand 2 "" "i")))
+   (clobber (reg:SI 1))
+   (clobber (reg:SI 2))
+   (clobber (reg:DF 48))
+   (use (const_int 1))]
+  "TARGET_HPUX && !TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
+  "*
+{
+  pa_output_arg_descriptor (insn);
+  return pa_output_call (insn, operands[1], 0);
 }"
   [(set_attr "type" "call")
-   (set (attr "length") (symbol_ref "attr_length_call (insn, 0)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_call (insn, 0)")))])
 
 (define_insn "call_val_symref_pic"
-  [(set (match_operand:SI 3 "register_operand" "=&r") (reg:SI 19))
-   (set (match_operand 0 "" "")
+  [(set (match_operand 0 "" "")
        (call (mem:SI (match_operand 1 "call_operand_address" ""))
              (match_operand 2 "" "i")))
    (clobber (reg:SI 1))
    (clobber (reg:SI 2))
-   (use (match_dup 3))
+   (clobber (match_operand 3))
    (use (reg:SI 19))
    (use (const_int 0))]
   "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
@@ -7867,13 +7747,12 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 ;; terminate the basic block.  The split has to contain more than one
 ;; insn.
 (define_split
-  [(parallel [(set (match_operand:SI 3 "register_operand" "") (reg:SI 19))
-             (set (match_operand 0 "" "")
+  [(parallel [(set (match_operand 0 "" "")
              (call (mem:SI (match_operand 1 "call_operand_address" ""))
                    (match_operand 2 "" "")))
              (clobber (reg:SI 1))
              (clobber (reg:SI 2))
-             (use (match_dup 3))
+             (clobber (match_operand 3))
              (use (reg:SI 19))
              (use (const_int 0))])]
   "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed
@@ -7889,13 +7768,12 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "")
 
 (define_split
-  [(parallel [(set (match_operand:SI 3 "register_operand" "") (reg:SI 19))
-             (set (match_operand 0 "" "")
+  [(parallel [(set (match_operand 0 "" "")
              (call (mem:SI (match_operand 1 "call_operand_address" ""))
                    (match_operand 2 "" "")))
              (clobber (reg:SI 1))
              (clobber (reg:SI 2))
-             (use (match_dup 3))
+             (clobber (match_operand 3))
              (use (reg:SI 19))
              (use (const_int 0))])]
   "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed"
@@ -7921,22 +7799,112 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
   "*
 {
-  output_arg_descriptor (insn);
-  return output_call (insn, operands[1], 0);
+  pa_output_arg_descriptor (insn);
+  return pa_output_call (insn, operands[1], 0);
+}"
+  [(set_attr "type" "call")
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_call (insn, 0)")))])
+
+;; powf function clobbers %fr12
+(define_insn "call_val_powf_pic"
+  [(set (match_operand 0 "" "")
+       (call (mem:SI (match_operand 1 "call_operand_address" ""))
+             (match_operand 2 "" "i")))
+   (clobber (reg:SI 1))
+   (clobber (reg:SI 2))
+   (clobber (reg:DF 48))
+   (clobber (match_operand 3))
+   (use (reg:SI 19))
+   (use (const_int 1))]
+  "TARGET_HPUX && !TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
+  "#")
+
+;; Split out the PIC register save and restore after reload.  As the
+;; split is done after reload, there are some situations in which we
+;; unnecessarily save and restore %r4.  This happens when there is a
+;; single call and the PIC register is not used after the call.
+;;
+;; The split has to be done since call_from_call_insn () can't handle
+;; the pattern as is.  Noreturn calls are special because they have to
+;; terminate the basic block.  The split has to contain more than one
+;; insn.
+(define_split
+  [(parallel [(set (match_operand 0 "" "")
+             (call (mem:SI (match_operand 1 "call_operand_address" ""))
+                   (match_operand 2 "" "")))
+             (clobber (reg:SI 1))
+             (clobber (reg:SI 2))
+             (clobber (reg:DF 48))
+             (clobber (match_operand 3))
+             (use (reg:SI 19))
+             (use (const_int 1))])]
+  "TARGET_HPUX && !TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed
+   && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+  [(set (match_dup 3) (reg:SI 19))
+   (parallel [(set (match_dup 0)
+             (call (mem:SI (match_dup 1))
+                   (match_dup 2)))
+             (clobber (reg:SI 1))
+             (clobber (reg:SI 2))
+             (clobber (reg:DF 48))
+             (use (reg:SI 19))
+             (use (const_int 1))])]
+  "")
+
+(define_split
+  [(parallel [(set (match_operand 0 "" "")
+             (call (mem:SI (match_operand 1 "call_operand_address" ""))
+                   (match_operand 2 "" "")))
+             (clobber (reg:SI 1))
+             (clobber (reg:SI 2))
+             (clobber (reg:DF 48))
+             (clobber (match_operand 3))
+             (use (reg:SI 19))
+             (use (const_int 1))])]
+  "TARGET_HPUX && !TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed"
+  [(set (match_dup 3) (reg:SI 19))
+   (parallel [(set (match_dup 0)
+             (call (mem:SI (match_dup 1))
+                   (match_dup 2)))
+             (clobber (reg:SI 1))
+             (clobber (reg:SI 2))
+             (clobber (reg:DF 48))
+             (use (reg:SI 19))
+             (use (const_int 1))])
+   (set (reg:SI 19) (match_dup 3))]
+  "")
+
+(define_insn "*call_val_powf_pic_post_reload"
+  [(set (match_operand 0 "" "")
+       (call (mem:SI (match_operand 1 "call_operand_address" ""))
+             (match_operand 2 "" "i")))
+   (clobber (reg:SI 1))
+   (clobber (reg:SI 2))
+   (clobber (reg:DF 48))
+   (use (reg:SI 19))
+   (use (const_int 1))]
+  "TARGET_HPUX && !TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
+  "*
+{
+  pa_output_arg_descriptor (insn);
+  return pa_output_call (insn, operands[1], 0);
 }"
   [(set_attr "type" "call")
-   (set (attr "length") (symbol_ref "attr_length_call (insn, 0)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_call (insn, 0)")))])
 
 ;; This pattern is split if it is necessary to save and restore the
 ;; PIC register.
 (define_insn "call_val_symref_64bit"
-  [(set (match_operand:DI 3 "register_operand" "=&r") (reg:DI 27))
-   (set (match_operand 0 "" "")
+  [(set (match_operand 0 "" "")
        (call (mem:SI (match_operand 1 "call_operand_address" ""))
              (match_operand 2 "" "i")))
    (clobber (reg:DI 1))
    (clobber (reg:DI 2))
-   (use (match_dup 3))
+   (clobber (match_operand 3))
    (use (reg:DI 27))
    (use (reg:DI 29))
    (use (const_int 0))]
@@ -7953,13 +7921,12 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 ;; terminate the basic block.  The split has to contain more than one
 ;; insn.
 (define_split
-  [(parallel [(set (match_operand:DI 3 "register_operand" "") (reg:DI 27))
-             (set (match_operand 0 "" "")
+  [(parallel [(set (match_operand 0 "" "")
              (call (mem:SI (match_operand 1 "call_operand_address" ""))
                    (match_operand 2 "" "")))
              (clobber (reg:DI 1))
              (clobber (reg:DI 2))
-             (use (match_dup 3))
+             (clobber (match_operand 3))
              (use (reg:DI 27))
              (use (reg:DI 29))
              (use (const_int 0))])]
@@ -7977,13 +7944,12 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "")
 
 (define_split
-  [(parallel [(set (match_operand:DI 3 "register_operand" "") (reg:DI 27))
-             (set (match_operand 0 "" "")
+  [(parallel [(set (match_operand 0 "" "")
              (call (mem:SI (match_operand 1 "call_operand_address" ""))
                    (match_operand 2 "" "")))
              (clobber (reg:DI 1))
              (clobber (reg:DI 2))
-             (use (match_dup 3))
+             (clobber (match_operand 3))
              (use (reg:DI 27))
              (use (reg:DI 29))
              (use (const_int 0))])]
@@ -8012,11 +7978,106 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "TARGET_64BIT"
   "*
 {
-  output_arg_descriptor (insn);
-  return output_call (insn, operands[1], 0);
+  return pa_output_call (insn, operands[1], 0);
 }"
   [(set_attr "type" "call")
-   (set (attr "length") (symbol_ref "attr_length_call (insn, 0)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_call (insn, 0)")))])
+
+;; powf function clobbers %fr12
+(define_insn "call_val_powf_64bit"
+  [(set (match_operand 0 "" "")
+       (call (mem:SI (match_operand 1 "call_operand_address" ""))
+             (match_operand 2 "" "i")))
+   (clobber (reg:DI 1))
+   (clobber (reg:DI 2))
+   (clobber (reg:DF 40))
+   (clobber (match_operand 3))
+   (use (reg:DI 27))
+   (use (reg:DI 29))
+   (use (const_int 1))]
+  "TARGET_64BIT && TARGET_HPUX"
+  "#")
+
+;; Split out the PIC register save and restore after reload.  As the
+;; split is done after reload, there are some situations in which we
+;; unnecessarily save and restore %r4.  This happens when there is a
+;; single call and the PIC register is not used after the call.
+;;
+;; The split has to be done since call_from_call_insn () can't handle
+;; the pattern as is.  Noreturn calls are special because they have to
+;; terminate the basic block.  The split has to contain more than one
+;; insn.
+(define_split
+  [(parallel [(set (match_operand 0 "" "")
+             (call (mem:SI (match_operand 1 "call_operand_address" ""))
+                   (match_operand 2 "" "")))
+             (clobber (reg:DI 1))
+             (clobber (reg:DI 2))
+             (clobber (reg:DF 40))
+             (clobber (match_operand 3))
+             (use (reg:DI 27))
+             (use (reg:DI 29))
+             (use (const_int 1))])]
+  "TARGET_64BIT && TARGET_HPUX && reload_completed
+   && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+  [(set (match_dup 3) (reg:DI 27))
+   (parallel [(set (match_dup 0)
+             (call (mem:SI (match_dup 1))
+                   (match_dup 2)))
+             (clobber (reg:DI 1))
+             (clobber (reg:DI 2))
+             (clobber (reg:DF 40))
+             (use (reg:DI 27))
+             (use (reg:DI 29))
+             (use (const_int 1))])]
+  "")
+
+(define_split
+  [(parallel [(set (match_operand 0 "" "")
+             (call (mem:SI (match_operand 1 "call_operand_address" ""))
+                   (match_operand 2 "" "")))
+             (clobber (reg:DI 1))
+             (clobber (reg:DI 2))
+             (clobber (reg:DF 40))
+             (clobber (match_operand 3))
+             (use (reg:DI 27))
+             (use (reg:DI 29))
+             (use (const_int 1))])]
+  "TARGET_64BIT && TARGET_HPUX && reload_completed"
+  [(set (match_dup 3) (reg:DI 27))
+   (parallel [(set (match_dup 0)
+             (call (mem:SI (match_dup 1))
+                   (match_dup 2)))
+             (clobber (reg:DI 1))
+             (clobber (reg:DI 2))
+             (clobber (reg:DF 40))
+             (use (reg:DI 27))
+             (use (reg:DI 29))
+             (use (const_int 1))])
+   (set (reg:DI 27) (match_dup 3))]
+  "")
+
+(define_insn "*call_val_powf_64bit_post_reload"
+  [(set (match_operand 0 "" "")
+       (call (mem:SI (match_operand 1 "call_operand_address" ""))
+             (match_operand 2 "" "i")))
+   (clobber (reg:DI 1))
+   (clobber (reg:DI 2))
+   (clobber (reg:DF 40))
+   (use (reg:DI 27))
+   (use (reg:DI 29))
+   (use (const_int 1))]
+  "TARGET_64BIT && TARGET_HPUX"
+  "*
+{
+  return pa_output_call (insn, operands[1], 0);
+}"
+  [(set_attr "type" "call")
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_call (insn, 0)")))])
 
 (define_insn "call_val_reg"
   [(set (match_operand 0 "" "")
@@ -8028,21 +8089,22 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "!TARGET_64BIT"
   "*
 {
-  return output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
+  return pa_output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
 }"
   [(set_attr "type" "dyncall")
-   (set (attr "length") (symbol_ref "attr_length_indirect_call (insn)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_indirect_call (insn)")))])
 
 ;; This pattern is split if it is necessary to save and restore the
 ;; PIC register.
 (define_insn "call_val_reg_pic"
-  [(set (match_operand:SI 2 "register_operand" "=&r") (reg:SI 19))
-   (set (match_operand 0 "" "")
+  [(set (match_operand 0 "" "")
        (call (mem:SI (reg:SI 22))
              (match_operand 1 "" "i")))
    (clobber (reg:SI 1))
    (clobber (reg:SI 2))
-   (use (match_dup 2))
+   (clobber (match_operand 2))
    (use (reg:SI 19))
    (use (const_int 1))]
   "!TARGET_64BIT"
@@ -8058,13 +8120,12 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 ;; terminate the basic block.  The split has to contain more than one
 ;; insn.
 (define_split
-  [(parallel [(set (match_operand:SI 2 "register_operand" "") (reg:SI 19))
-             (set (match_operand 0 "" "")
+  [(parallel [(set (match_operand 0 "" "")
                   (call (mem:SI (reg:SI 22))
                         (match_operand 1 "" "")))
              (clobber (reg:SI 1))
              (clobber (reg:SI 2))
-             (use (match_dup 2))
+             (clobber (match_operand 2))
              (use (reg:SI 19))
              (use (const_int 1))])]
   "!TARGET_64BIT && reload_completed
@@ -8080,13 +8141,12 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "")
 
 (define_split
-  [(parallel [(set (match_operand:SI 2 "register_operand" "") (reg:SI 19))
-             (set (match_operand 0 "" "")
+  [(parallel [(set (match_operand 0 "" "")
                   (call (mem:SI (reg:SI 22))
                         (match_operand 1 "" "")))
              (clobber (reg:SI 1))
              (clobber (reg:SI 2))
-             (use (match_dup 2))
+             (clobber (match_operand 2))
              (use (reg:SI 19))
              (use (const_int 1))])]
   "!TARGET_64BIT && reload_completed"
@@ -8112,100 +8172,259 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "!TARGET_64BIT"
   "*
 {
-  return output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
+  return pa_output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
 }"
   [(set_attr "type" "dyncall")
-   (set (attr "length") (symbol_ref "attr_length_indirect_call (insn)"))])
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_indirect_call (insn)")))])
 
 ;; This pattern is split if it is necessary to save and restore the
 ;; PIC register.
 (define_insn "call_val_reg_64bit"
-  [(set (match_operand:DI 3 "register_operand" "=&r") (reg:DI 27))
-   (set (match_operand 0 "" "")
+  [(set (match_operand 0 "" "")
        (call (mem:SI (match_operand:DI 1 "register_operand" "r"))
              (match_operand 2 "" "i")))
-   (clobber (reg:DI 1))
    (clobber (reg:DI 2))
-   (use (match_dup 3))
+   (clobber (match_operand 3))
+   (use (reg:DI 27))
+   (use (reg:DI 29))
+   (use (const_int 1))]
+  "TARGET_64BIT"
+  "#")
+
+;; Split out the PIC register save and restore after reload.  As the
+;; split is done after reload, there are some situations in which we
+;; unnecessarily save and restore %r4.  This happens when there is a
+;; single call and the PIC register is not used after the call.
+;;
+;; The split has to be done since call_from_call_insn () can't handle
+;; the pattern as is.  Noreturn calls are special because they have to
+;; terminate the basic block.  The split has to contain more than one
+;; insn.
+(define_split
+  [(parallel [(set (match_operand 0 "" "")
+                  (call (mem:SI (match_operand:DI 1 "register_operand" ""))
+                        (match_operand 2 "" "")))
+             (clobber (reg:DI 2))
+             (clobber (match_operand 3))
+             (use (reg:DI 27))
+             (use (reg:DI 29))
+             (use (const_int 1))])]
+  "TARGET_64BIT && reload_completed
+   && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+  [(set (match_dup 3) (reg:DI 27))
+   (parallel [(set (match_dup 0)
+                  (call (mem:SI (match_dup 1))
+                        (match_dup 2)))
+             (clobber (reg:DI 2))
+             (use (reg:DI 27))
+             (use (reg:DI 29))
+             (use (const_int 1))])]
+  "")
+
+(define_split
+  [(parallel [(set (match_operand 0 "" "")
+                  (call (mem:SI (match_operand:DI 1 "register_operand" ""))
+                        (match_operand 2 "" "")))
+             (clobber (reg:DI 2))
+             (clobber (match_operand 3))
+             (use (reg:DI 27))
+             (use (reg:DI 29))
+             (use (const_int 1))])]
+  "TARGET_64BIT && reload_completed"
+  [(set (match_dup 3) (reg:DI 27))
+   (parallel [(set (match_dup 0)
+                  (call (mem:SI (match_dup 1))
+                        (match_dup 2)))
+             (clobber (reg:DI 2))
+             (use (reg:DI 27))
+             (use (reg:DI 29))
+             (use (const_int 1))])
+   (set (reg:DI 27) (match_dup 3))]
+  "")
+
+(define_insn "*call_val_reg_64bit_post_reload"
+  [(set (match_operand 0 "" "")
+       (call (mem:SI (match_operand:DI 1 "register_operand" "r"))
+             (match_operand 2 "" "i")))
+   (clobber (reg:DI 2))
+   (use (reg:DI 27))
+   (use (reg:DI 29))
+   (use (const_int 1))]
+  "TARGET_64BIT"
+  "*
+{
+  return pa_output_indirect_call (insn, operands[1]);
+}"
+  [(set_attr "type" "dyncall")
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 12)]
+             (symbol_ref "pa_attr_length_indirect_call (insn)")))])
+
+/* Expand special pc-relative call to _mcount.  */
+
+(define_expand "call_mcount"
+  [(parallel [(call (match_operand:SI 0 "" "")
+                   (match_operand 1 "" ""))
+             (set (reg:SI 25)
+                  (plus:SI (reg:SI 2)
+                           (minus:SI (match_operand 2 "" "")
+                                     (plus:SI (pc) (const_int 4)))))
+             (clobber (reg:SI 2))])]
+  "!TARGET_PORTABLE_RUNTIME"
+  "
+{
+  rtx op = XEXP (operands[0], 0);
+  rtx nb = operands[1];
+  rtx lab = operands[2];
+
+  if (TARGET_64BIT)
+    {
+      rtx r4 = gen_rtx_REG (word_mode, 4);
+      emit_move_insn (arg_pointer_rtx,
+                     gen_rtx_PLUS (word_mode, virtual_outgoing_args_rtx,
+                                   GEN_INT (64)));
+      emit_call_insn (gen_call_mcount_64bit (op, nb, lab, r4));
+    }
+  else
+    {
+      if (flag_pic)
+       {
+         rtx r4 = gen_rtx_REG (word_mode, 4);
+         emit_call_insn (gen_call_mcount_pic (op, nb, lab, r4));
+       }
+      else
+       emit_call_insn (gen_call_mcount_nonpic (op, nb, lab));
+    }
+
+  DONE;
+}")
+
+(define_insn "call_mcount_nonpic"
+  [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+        (match_operand 1 "" "i"))
+   (set (reg:SI 25)
+       (plus:SI (reg:SI 2)
+                (minus:SI (match_operand 2 "" "")
+                          (plus:SI (pc) (const_int 4)))))
+   (clobber (reg:SI 2))]
+  "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
+  "*
+{
+  pa_output_arg_descriptor (insn);
+  return \"{bl|b,l} %0,%%r2\;ldo %2-.-4(%%r2),%%r25\";
+}"
+  [(set_attr "type" "multi")
+   (set_attr "length" "8")])
+
+(define_insn "call_mcount_pic"
+  [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+        (match_operand 1 "" "i"))
+   (set (reg:SI 25)
+       (plus:SI (reg:SI 2)
+                (minus:SI (match_operand 2 "" "")
+                          (plus:SI (pc) (const_int 4)))))
+   (clobber (reg:SI 2))
+   (clobber (match_operand 3))
+   (use (reg:SI 19))]
+  "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
+  "#")
+
+(define_split
+  [(parallel [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+                   (match_operand 1 "" ""))
+             (set (reg:SI 25)
+                  (plus:SI (reg:SI 2)
+                           (minus:SI (match_operand 2 "" "")
+                                     (plus:SI (pc) (const_int 4)))))
+             (clobber (reg:SI 2))
+             (clobber (match_operand 3))
+             (use (reg:SI 19))])]
+  "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed"
+  [(set (match_dup 3) (reg:SI 19))
+   (parallel [(call (mem:SI (match_dup 0))
+                   (match_dup 1))
+             (set (reg:SI 25)
+                  (plus:SI (reg:SI 2)
+                           (minus:SI (match_dup 2)
+                                     (plus:SI (pc) (const_int 4)))))
+             (clobber (reg:SI 2))
+             (use (reg:SI 19))])
+   (set (reg:SI 19) (match_dup 3))]
+  "")
+
+(define_insn "*call_mcount_pic_post_reload"
+  [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+        (match_operand 1 "" "i"))
+   (set (reg:SI 25)
+       (plus:SI (reg:SI 2)
+                (minus:SI (match_operand 2 "" "")
+                          (plus:SI (pc) (const_int 4)))))
+   (clobber (reg:SI 2))
+   (use (reg:SI 19))]
+  "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
+  "*
+{
+  pa_output_arg_descriptor (insn);
+  return \"{bl|b,l} %0,%%r2\;ldo %2-.-4(%%r2),%%r25\";
+}"
+  [(set_attr "type" "multi")
+   (set_attr "length" "8")])
+
+(define_insn "call_mcount_64bit"
+  [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+        (match_operand 1 "" "i"))
+   (set (reg:SI 25)
+       (plus:SI (reg:SI 2)
+                (minus:SI (match_operand 2 "" "")
+                          (plus:SI (pc) (const_int 4)))))
+   (clobber (reg:DI 2))
+   (clobber (match_operand 3))
    (use (reg:DI 27))
-   (use (reg:DI 29))
-   (use (const_int 1))]
+   (use (reg:DI 29))]
   "TARGET_64BIT"
   "#")
 
-;; Split out the PIC register save and restore after reload.  As the
-;; split is done after reload, there are some situations in which we
-;; unnecessarily save and restore %r4.  This happens when there is a
-;; single call and the PIC register is not used after the call.
-;;
-;; The split has to be done since call_from_call_insn () can't handle
-;; the pattern as is.  Noreturn calls are special because they have to
-;; terminate the basic block.  The split has to contain more than one
-;; insn.
-(define_split
-  [(parallel [(set (match_operand:DI 3 "register_operand" "") (reg:DI 27))
-             (set (match_operand 0 "" "")
-                  (call (mem:SI (match_operand:DI 1 "register_operand" ""))
-                        (match_operand 2 "" "")))
-             (clobber (reg:DI 1))
-             (clobber (reg:DI 2))
-             (use (match_dup 3))
-             (use (reg:DI 27))
-             (use (reg:DI 29))
-             (use (const_int 1))])]
-  "TARGET_64BIT && reload_completed
-   && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
-  [(set (match_dup 3) (reg:DI 27))
-   (parallel [(set (match_dup 0)
-                  (call (mem:SI (match_dup 1))
-                        (match_dup 2)))
-             (clobber (reg:DI 1))
-             (clobber (reg:DI 2))
-             (use (reg:DI 27))
-             (use (reg:DI 29))
-             (use (const_int 1))])]
-  "")
-
 (define_split
-  [(parallel [(set (match_operand:DI 3 "register_operand" "") (reg:DI 27))
-             (set (match_operand 0 "" "")
-                  (call (mem:SI (match_operand:DI 1 "register_operand" ""))
-                        (match_operand 2 "" "")))
-             (clobber (reg:DI 1))
+  [(parallel [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+                   (match_operand 1 "" ""))
+             (set (reg:SI 25)
+                  (plus:SI (reg:SI 2)
+                           (minus:SI (match_operand 2 "" "")
+                                     (plus:SI (pc) (const_int 4)))))
              (clobber (reg:DI 2))
-             (use (match_dup 3))
+             (clobber (match_operand 3))
              (use (reg:DI 27))
-             (use (reg:DI 29))
-             (use (const_int 1))])]
+             (use (reg:DI 29))])]
   "TARGET_64BIT && reload_completed"
   [(set (match_dup 3) (reg:DI 27))
-   (parallel [(set (match_dup 0)
-                  (call (mem:SI (match_dup 1))
-                        (match_dup 2)))
-             (clobber (reg:DI 1))
+   (parallel [(call (mem:SI (match_dup 0))
+                   (match_dup 1))
+             (set (reg:SI 25)
+                  (plus:SI (reg:SI 2)
+                           (minus:SI (match_dup 2)
+                                     (plus:SI (pc) (const_int 4)))))
              (clobber (reg:DI 2))
              (use (reg:DI 27))
-             (use (reg:DI 29))
-             (use (const_int 1))])
+             (use (reg:DI 29))])
    (set (reg:DI 27) (match_dup 3))]
   "")
 
-(define_insn "*call_val_reg_64bit_post_reload"
-  [(set (match_operand 0 "" "")
-       (call (mem:SI (match_operand:DI 1 "register_operand" "r"))
-             (match_operand 2 "" "i")))
-   (clobber (reg:DI 1))
+(define_insn "*call_mcount_64bit_post_reload"
+  [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+        (match_operand 1 "" "i"))
+   (set (reg:SI 25)
+       (plus:SI (reg:SI 2)
+                (minus:SI (match_operand 2 "" "")
+                          (plus:SI (pc) (const_int 4)))))
    (clobber (reg:DI 2))
    (use (reg:DI 27))
-   (use (reg:DI 29))
-   (use (const_int 1))]
+   (use (reg:DI 29))]
   "TARGET_64BIT"
-  "*
-{
-  return output_indirect_call (insn, operands[1]);
-}"
-  [(set_attr "type" "dyncall")
-   (set (attr "length") (symbol_ref "attr_length_indirect_call (insn)"))])
+  "{bl|b,l} %0,%%r2\;ldo %2-.-4(%%r2),%%r25"
+  [(set_attr "type" "multi")
+   (set_attr "length" "8")])
 
 ;; Call subroutine returning any type.
 
@@ -8219,7 +8438,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 {
   int i;
 
-  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+  emit_call_insn (gen_call (operands[0], const0_rtx));
 
   for (i = 0; i < XVECLEN (operands[2], 0); i++)
     {
@@ -8295,11 +8514,13 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
   "*
 {
-  output_arg_descriptor (insn);
-  return output_call (insn, operands[0], 1);
+  pa_output_arg_descriptor (insn);
+  return pa_output_call (insn, operands[0], 1);
 }"
-  [(set_attr "type" "call")
-   (set (attr "length") (symbol_ref "attr_length_call (insn, 1)"))])
+  [(set_attr "type" "sibcall")
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_call (insn, 1)")))])
 
 (define_insn "sibcall_internal_symref_64bit"
   [(call (mem:SI (match_operand 0 "call_operand_address" ""))
@@ -8310,11 +8531,12 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "TARGET_64BIT"
   "*
 {
-  output_arg_descriptor (insn);
-  return output_call (insn, operands[0], 1);
+  return pa_output_call (insn, operands[0], 1);
 }"
-  [(set_attr "type" "call")
-   (set (attr "length") (symbol_ref "attr_length_call (insn, 1)"))])
+  [(set_attr "type" "sibcall")
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_call (insn, 1)")))])
 
 (define_expand "sibcall_value"
   [(set (match_operand 0 "" "")
@@ -8379,11 +8601,13 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
   "*
 {
-  output_arg_descriptor (insn);
-  return output_call (insn, operands[1], 1);
+  pa_output_arg_descriptor (insn);
+  return pa_output_call (insn, operands[1], 1);
 }"
-  [(set_attr "type" "call")
-   (set (attr "length") (symbol_ref "attr_length_call (insn, 1)"))])
+  [(set_attr "type" "sibcall")
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_call (insn, 1)")))])
 
 (define_insn "sibcall_value_internal_symref_64bit"
   [(set (match_operand 0 "" "")
@@ -8395,11 +8619,12 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "TARGET_64BIT"
   "*
 {
-  output_arg_descriptor (insn);
-  return output_call (insn, operands[1], 1);
+  return pa_output_call (insn, operands[1], 1);
 }"
-  [(set_attr "type" "call")
-   (set (attr "length") (symbol_ref "attr_length_call (insn, 1)"))])
+  [(set_attr "type" "sibcall")
+   (set (attr "length")
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+             (symbol_ref "pa_attr_length_call (insn, 1)")))])
 
 (define_insn "nop"
   [(const_int 0)]
@@ -8408,36 +8633,6 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   [(set_attr "type" "move")
    (set_attr "length" "4")])
 
-;; These are just placeholders so we know where branch tables
-;; begin and end.
-(define_insn "begin_brtab"
-  [(const_int 1)]
-  ""
-  "*
-{
-  /* Only GAS actually supports this pseudo-op.  */
-  if (TARGET_GAS)
-    return \".begin_brtab\";
-  else
-    return \"\";
-}"
-  [(set_attr "type" "move")
-   (set_attr "length" "0")])
-
-(define_insn "end_brtab"
-  [(const_int 2)]
-  ""
-  "*
-{
-  /* Only GAS actually supports this pseudo-op.  */
-  if (TARGET_GAS)
-    return \".end_brtab\";
-  else
-    return \"\";
-}"
-  [(set_attr "type" "move")
-   (set_attr "length" "0")])
-
 ;;; EH does longjmp's from and within the data section.  Thus,
 ;;; an interspace branch is required for the longjmp implementation.
 ;;; Registers r1 and r2 are used as scratch registers for the jump
@@ -8491,37 +8686,33 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 {
   /* The elements of the buffer are, in order:  */
   rtx fp = gen_rtx_MEM (Pmode, operands[0]);
-  rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0],
+  rtx lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
                         POINTER_SIZE / BITS_PER_UNIT));
-  rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0],
+  rtx stack = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
                           (POINTER_SIZE * 2) / BITS_PER_UNIT));
   rtx pv = gen_rtx_REG (Pmode, 1);
 
   emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
   emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
 
-  /* Restore the frame pointer.  The virtual_stack_vars_rtx is saved
-     instead of the hard_frame_pointer_rtx in the save area.  We need
-     to adjust for the offset between these two values when we have
-     a nonlocal_goto pattern.  When we don't have a nonlocal_goto
-     pattern, the receiver performs the adjustment.  */
-#ifdef HAVE_nonlocal_goto
-  if (HAVE_nonlocal_goto)
-    emit_move_insn (virtual_stack_vars_rtx, force_reg (Pmode, fp));
-  else
-#endif
-    emit_move_insn (hard_frame_pointer_rtx, fp);
-
-  /* This bit is the same as expand_builtin_longjmp.  */
-  emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
-  emit_use (hard_frame_pointer_rtx);
-  emit_use (stack_pointer_rtx);
-
   /* Load the label we are jumping through into r1 so that we know
      where to look for it when we get back to setjmp's function for
      restoring the gp.  */
   emit_move_insn (pv, lab);
 
+  /* Restore the stack and frame pointers.  */
+  fp = copy_to_reg (fp);
+  emit_stack_restore (SAVE_NONLOCAL, stack);
+
+  /* Ensure the frame pointer move is not optimized.  */
+  emit_insn (gen_blockage ());
+  emit_clobber (hard_frame_pointer_rtx);
+  emit_clobber (frame_pointer_rtx);
+  emit_move_insn (hard_frame_pointer_rtx, fp);
+
+  emit_use (hard_frame_pointer_rtx);
+  emit_use (stack_pointer_rtx);
+
   /* Prevent the insns above from being scheduled into the delay slot
      of the interspace jump because the space register could change.  */
   emit_insn (gen_blockage ());
@@ -8532,21 +8723,22 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 }")
 
 ;;; Operands 2 and 3 are assumed to be CONST_INTs.
-(define_expand "extzv"
-  [(set (match_operand 0 "register_operand" "")
-       (zero_extract (match_operand 1 "register_operand" "")
-                     (match_operand 2 "uint32_operand" "")
-                     (match_operand 3 "uint32_operand" "")))]
+(define_expand "extzvsi"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (zero_extract:SI (match_operand:SI 1 "register_operand" "")
+                        (match_operand:SI 2 "uint5_operand" "")
+                        (match_operand:SI 3 "uint5_operand" "")))]
   ""
   "
 {
-  HOST_WIDE_INT len = INTVAL (operands[2]);
-  HOST_WIDE_INT pos = INTVAL (operands[3]);
+  unsigned HOST_WIDE_INT len = UINTVAL (operands[2]);
+  unsigned HOST_WIDE_INT pos = UINTVAL (operands[3]);
 
   /* PA extraction insns don't support zero length bitfields or fields
-     extending beyond the left or right-most bits.  Also, we reject lengths
-     equal to a word as they are better handled by the move patterns.  */
-  if (len <= 0 || len >= BITS_PER_WORD || pos < 0 || pos + len > BITS_PER_WORD)
+     extending beyond the left or right-most bits.  Also, the predicate
+     rejects lengths equal to a word as they are better handled by
+     the move patterns.  */
+  if (len == 0 || pos + len > 32)
     FAIL;
 
   /* From mips.md: extract_bit_field doesn't verify that our source
@@ -8554,12 +8746,8 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   if (!register_operand (operands[1], VOIDmode))
     FAIL;
 
-  if (TARGET_64BIT)
-    emit_insn (gen_extzv_64 (operands[0], operands[1],
-                            operands[2], operands[3]));
-  else
-    emit_insn (gen_extzv_32 (operands[0], operands[1],
-                            operands[2], operands[3]));
+  emit_insn (gen_extzv_32 (operands[0], operands[1],
+                          operands[2], operands[3]));
   DONE;
 }")
 
@@ -8568,7 +8756,8 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
        (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
                         (match_operand:SI 2 "uint5_operand" "")
                         (match_operand:SI 3 "uint5_operand" "")))]
-  ""
+  "UINTVAL (operands[2]) > 0
+   && UINTVAL (operands[2]) + UINTVAL (operands[3]) <= 32"
   "{extru|extrw,u} %1,%3+%2-1,%2,%0"
   [(set_attr "type" "shift")
    (set_attr "length" "4")])
@@ -8583,12 +8772,42 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   [(set_attr "type" "shift")
    (set_attr "length" "4")])
 
+(define_expand "extzvdi"
+  [(set (match_operand:DI 0 "register_operand" "")
+       (zero_extract:DI (match_operand:DI 1 "register_operand" "")
+                        (match_operand:DI 2 "uint6_operand" "")
+                        (match_operand:DI 3 "uint6_operand" "")))]
+  "TARGET_64BIT"
+  "
+{
+  unsigned HOST_WIDE_INT len = UINTVAL (operands[2]);
+  unsigned HOST_WIDE_INT pos = UINTVAL (operands[3]);
+
+  /* PA extraction insns don't support zero length bitfields or fields
+     extending beyond the left or right-most bits.  Also, the predicate
+     rejects lengths equal to a doubleword as they are better handled by
+     the move patterns.  */
+  if (len == 0 || pos + len > 64)
+    FAIL;
+
+  /* From mips.md: extract_bit_field doesn't verify that our source
+     matches the predicate, so check it again here.  */
+  if (!register_operand (operands[1], VOIDmode))
+    FAIL;
+
+  emit_insn (gen_extzv_64 (operands[0], operands[1],
+                          operands[2], operands[3]));
+  DONE;
+}")
+
 (define_insn "extzv_64"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extract:DI (match_operand:DI 1 "register_operand" "r")
-                        (match_operand:DI 2 "uint32_operand" "")
-                        (match_operand:DI 3 "uint32_operand" "")))]
-  "TARGET_64BIT"
+                        (match_operand:DI 2 "uint6_operand" "")
+                        (match_operand:DI 3 "uint6_operand" "")))]
+  "TARGET_64BIT
+   && UINTVAL (operands[2]) > 0
+   && UINTVAL (operands[2]) + UINTVAL (operands[3]) <= 64"
   "extrd,u %1,%3+%2-1,%2,%0"
   [(set_attr "type" "shift")
    (set_attr "length" "4")])
@@ -8604,21 +8823,22 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
    (set_attr "length" "4")])
 
 ;;; Operands 2 and 3 are assumed to be CONST_INTs.
-(define_expand "extv"
-  [(set (match_operand 0 "register_operand" "")
-       (sign_extract (match_operand 1 "register_operand" "")
-                     (match_operand 2 "uint32_operand" "")
-                     (match_operand 3 "uint32_operand" "")))]
+(define_expand "extvsi"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (sign_extract:SI (match_operand:SI 1 "register_operand" "")
+                        (match_operand:SI 2 "uint5_operand" "")
+                        (match_operand:SI 3 "uint5_operand" "")))]
   ""
   "
 {
-  HOST_WIDE_INT len = INTVAL (operands[2]);
-  HOST_WIDE_INT pos = INTVAL (operands[3]);
+  unsigned HOST_WIDE_INT len = UINTVAL (operands[2]);
+  unsigned HOST_WIDE_INT pos = UINTVAL (operands[3]);
 
   /* PA extraction insns don't support zero length bitfields or fields
-     extending beyond the left or right-most bits.  Also, we reject lengths
-     equal to a word as they are better handled by the move patterns.  */
-  if (len <= 0 || len >= BITS_PER_WORD || pos < 0 || pos + len > BITS_PER_WORD)
+     extending beyond the left or right-most bits.  Also, the predicate
+     rejects lengths equal to a word as they are better handled by
+     the move patterns.  */
+  if (len == 0 || pos + len > 32)
     FAIL;
 
   /* From mips.md: extract_bit_field doesn't verify that our source
@@ -8626,12 +8846,8 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   if (!register_operand (operands[1], VOIDmode))
     FAIL;
 
-  if (TARGET_64BIT)
-    emit_insn (gen_extv_64 (operands[0], operands[1],
-                           operands[2], operands[3]));
-  else
-    emit_insn (gen_extv_32 (operands[0], operands[1],
-                           operands[2], operands[3]));
+  emit_insn (gen_extv_32 (operands[0], operands[1],
+                         operands[2], operands[3]));
   DONE;
 }")
 
@@ -8640,7 +8856,8 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
        (sign_extract:SI (match_operand:SI 1 "register_operand" "r")
                         (match_operand:SI 2 "uint5_operand" "")
                         (match_operand:SI 3 "uint5_operand" "")))]
-  ""
+  "UINTVAL (operands[2]) > 0
+   && UINTVAL (operands[2]) + UINTVAL (operands[3]) <= 32"
   "{extrs|extrw,s} %1,%3+%2-1,%2,%0"
   [(set_attr "type" "shift")
    (set_attr "length" "4")])
@@ -8655,12 +8872,42 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   [(set_attr "type" "shift")
    (set_attr "length" "4")])
 
+(define_expand "extvdi"
+  [(set (match_operand:DI 0 "register_operand" "")
+       (sign_extract:DI (match_operand:DI 1 "register_operand" "")
+                        (match_operand:DI 2 "uint6_operand" "")
+                        (match_operand:DI 3 "uint6_operand" "")))]
+  "TARGET_64BIT"
+  "
+{
+  unsigned HOST_WIDE_INT len = UINTVAL (operands[2]);
+  unsigned HOST_WIDE_INT pos = UINTVAL (operands[3]);
+
+  /* PA extraction insns don't support zero length bitfields or fields
+     extending beyond the left or right-most bits.  Also, the predicate
+     rejects lengths equal to a doubleword as they are better handled by
+     the move patterns.  */
+  if (len == 0 || pos + len > 64)
+    FAIL;
+
+  /* From mips.md: extract_bit_field doesn't verify that our source
+     matches the predicate, so check it again here.  */
+  if (!register_operand (operands[1], VOIDmode))
+    FAIL;
+
+  emit_insn (gen_extv_64 (operands[0], operands[1],
+                         operands[2], operands[3]));
+  DONE;
+}")
+
 (define_insn "extv_64"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (sign_extract:DI (match_operand:DI 1 "register_operand" "r")
-                        (match_operand:DI 2 "uint32_operand" "")
-                        (match_operand:DI 3 "uint32_operand" "")))]
-  "TARGET_64BIT"
+                        (match_operand:DI 2 "uint6_operand" "")
+                        (match_operand:DI 3 "uint6_operand" "")))]
+  "TARGET_64BIT
+   && UINTVAL (operands[2]) > 0
+   && UINTVAL (operands[2]) + UINTVAL (operands[3]) <= 64"
   "extrd,s %1,%3+%2-1,%2,%0"
   [(set_attr "type" "shift")
    (set_attr "length" "4")])
@@ -8676,21 +8923,22 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
    (set_attr "length" "4")])
 
 ;;; Operands 1 and 2 are assumed to be CONST_INTs.
-(define_expand "insv"
-  [(set (zero_extract (match_operand 0 "register_operand" "")
-                      (match_operand 1 "uint32_operand" "")
-                      (match_operand 2 "uint32_operand" ""))
-        (match_operand 3 "arith5_operand" ""))]
+(define_expand "insvsi"
+  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "")
+                        (match_operand:SI 1 "uint5_operand" "")
+                        (match_operand:SI 2 "uint5_operand" ""))
+       (match_operand:SI 3 "arith5_operand" ""))]
   ""
   "
 {
-  HOST_WIDE_INT len = INTVAL (operands[1]);
-  HOST_WIDE_INT pos = INTVAL (operands[2]);
+  unsigned HOST_WIDE_INT len = UINTVAL (operands[1]);
+  unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
 
   /* PA insertion insns don't support zero length bitfields or fields
-     extending beyond the left or right-most bits.  Also, we reject lengths
-     equal to a word as they are better handled by the move patterns.  */
-  if (len <= 0 || len >= BITS_PER_WORD || pos < 0 || pos + len > BITS_PER_WORD)
+     extending beyond the left or right-most bits.  Also, the predicate
+     rejects lengths equal to a word as they are better handled by
+     the move patterns.  */
+  if (len <= 0 || pos + len > 32)
     FAIL;
 
   /* From mips.md: insert_bit_field doesn't verify that our destination
@@ -8698,12 +8946,8 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   if (!register_operand (operands[0], VOIDmode))
     FAIL;
 
-  if (TARGET_64BIT)
-    emit_insn (gen_insv_64 (operands[0], operands[1],
-                           operands[2], operands[3]));
-  else
-    emit_insn (gen_insv_32 (operands[0], operands[1],
-                           operands[2], operands[3]));
+  emit_insn (gen_insv_32 (operands[0], operands[1],
+                         operands[2], operands[3]));
   DONE;
 }")
 
@@ -8712,7 +8956,8 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
                         (match_operand:SI 1 "uint5_operand" "")
                         (match_operand:SI 2 "uint5_operand" ""))
        (match_operand:SI 3 "arith5_operand" "r,L"))]
-  ""
+  "UINTVAL (operands[1]) > 0
+   && UINTVAL (operands[1]) + UINTVAL (operands[2]) <= 32"
   "@
    {dep|depw} %3,%2+%1-1,%1,%0
    {depi|depwi} %3,%2+%1-1,%1,%0"
@@ -8735,12 +8980,42 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   [(set_attr "type" "shift")
    (set_attr "length" "4")])
 
+(define_expand "insvdi"
+  [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "")
+                        (match_operand:DI 1 "uint6_operand" "")
+                        (match_operand:DI 2 "uint6_operand" ""))
+       (match_operand:DI 3 "arith5_operand" ""))]
+  "TARGET_64BIT"
+  "
+{
+  unsigned HOST_WIDE_INT len = UINTVAL (operands[1]);
+  unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
+
+  /* PA insertion insns don't support zero length bitfields or fields
+     extending beyond the left or right-most bits.  Also, the predicate
+     rejects lengths equal to a doubleword as they are better handled by
+     the move patterns.  */
+  if (len <= 0 || pos + len > 64)
+    FAIL;
+
+  /* From mips.md: insert_bit_field doesn't verify that our destination
+     matches the predicate, so check it again here.  */
+  if (!register_operand (operands[0], VOIDmode))
+    FAIL;
+
+  emit_insn (gen_insv_64 (operands[0], operands[1],
+                         operands[2], operands[3]));
+  DONE;
+}")
+
 (define_insn "insv_64"
   [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r,r")
-                        (match_operand:DI 1 "uint32_operand" "")
-                        (match_operand:DI 2 "uint32_operand" ""))
-       (match_operand:DI 3 "arith32_operand" "r,L"))]
-  "TARGET_64BIT"
+                        (match_operand:DI 1 "uint6_operand" "")
+                        (match_operand:DI 2 "uint6_operand" ""))
+       (match_operand:DI 3 "arith5_operand" "r,L"))]
+  "TARGET_64BIT
+   && UINTVAL (operands[1]) > 0
+   && UINTVAL (operands[1]) + UINTVAL (operands[2]) <= 64"
   "@
    depd %3,%2+%1-1,%1,%0
    depdi %3,%2+%1-1,%1,%0"
@@ -8750,8 +9025,8 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 ;; Optimize insertion of const_int values of type 1...1xxxx.
 (define_insn ""
   [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
-                        (match_operand:DI 1 "uint32_operand" "")
-                        (match_operand:DI 2 "uint32_operand" ""))
+                        (match_operand:DI 1 "uint6_operand" "")
+                        (match_operand:DI 2 "uint6_operand" ""))
        (match_operand:DI 3 "const_int_operand" ""))]
   "(INTVAL (operands[3]) & 0x10) != 0
    && TARGET_64BIT
@@ -8777,14 +9052,14 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 ;; strength reduction is used.  It is actually created when the instruction
 ;; combination phase combines the special loop test.  Since this insn
 ;; is both a jump insn and has an output, it must deal with its own
-;; reloads, hence the `m' constraints.  The `!' constraints direct reload
+;; reloads, hence the `Q' constraints.  The `!' constraints direct reload
 ;; to not choose the register alternatives in the event a reload is needed.
 (define_insn "decrement_and_branch_until_zero"
   [(set (pc)
        (if_then_else
          (match_operator 2 "comparison_operator"
           [(plus:SI
-             (match_operand:SI 0 "reg_before_reload_operand" "+!r,!*f,*m")
+             (match_operand:SI 0 "reg_before_reload_operand" "+!r,!*f,*Q")
              (match_operand:SI 1 "int5_operand" "L,L,L"))
            (const_int 0)])
          (label_ref (match_operand 3 "" ""))
@@ -8793,7 +9068,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
        (plus:SI (match_dup 0) (match_dup 1)))
    (clobber (match_scratch:SI 4 "=X,r,r"))]
   ""
-  "* return output_dbra (operands, insn, which_alternative); "
+  "* return pa_output_dbra (operands, insn, which_alternative); "
 ;; Do not expect to understand this the first time through.
 [(set_attr "type" "cbranch,multi,multi")
  (set (attr "length")
@@ -8807,9 +9082,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
           (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28))
 
@@ -8823,9 +9098,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
                    (lt (abs (minus (match_dup 3) (plus (pc) (const_int 24))))
                      (const_int MAX_17BIT_OFFSET))
                    (const_int 28)
-                   (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+                   (match_test "TARGET_PORTABLE_RUNTIME")
                    (const_int 44)
-                   (eq (symbol_ref "flag_pic") (const_int 0))
+                   (not (match_test "flag_pic"))
                    (const_int 40)]
                  (const_int 48))
             (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
@@ -8834,9 +9109,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
                    (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
                      (const_int MAX_17BIT_OFFSET))
                    (const_int 28)
-                   (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+                   (match_test "TARGET_PORTABLE_RUNTIME")
                    (const_int 44)
-                   (eq (symbol_ref "flag_pic") (const_int 0))
+                   (not (match_test "flag_pic"))
                    (const_int 40)]
                  (const_int 48)))
 
@@ -8849,9 +9124,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
                    (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
                      (const_int MAX_17BIT_OFFSET))
                    (const_int 16)
-                   (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+                   (match_test "TARGET_PORTABLE_RUNTIME")
                    (const_int 32)
-                   (eq (symbol_ref "flag_pic") (const_int 0))
+                   (not (match_test "flag_pic"))
                    (const_int 28)]
                  (const_int 36))
             (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
@@ -8860,9 +9135,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
                    (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
                      (const_int MAX_17BIT_OFFSET))
                    (const_int 16)
-                   (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+                   (match_test "TARGET_PORTABLE_RUNTIME")
                    (const_int 32)
-                   (eq (symbol_ref "flag_pic") (const_int 0))
+                   (not (match_test "flag_pic"))
                    (const_int 28)]
                  (const_int 36))))))])
 
@@ -8873,10 +9148,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
           [(match_operand:SI 1 "register_operand" "r,r,r,r") (const_int 0)])
          (label_ref (match_operand 3 "" ""))
          (pc)))
-   (set (match_operand:SI 0 "reg_before_reload_operand" "=!r,!*f,*m,!*q")
+   (set (match_operand:SI 0 "reg_before_reload_operand" "=!r,!*f,*Q,!*q")
        (match_dup 1))]
   ""
-"* return output_movb (operands, insn, which_alternative, 0); "
+"* return pa_output_movb (operands, insn, which_alternative, 0); "
 ;; Do not expect to understand this the first time through.
 [(set_attr "type" "cbranch,multi,multi,multi")
  (set (attr "length")
@@ -8890,9 +9165,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
           (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28))
 
@@ -8906,9 +9181,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
                    (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
                      (const_int MAX_17BIT_OFFSET))
                    (const_int 16)
-                   (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+                   (match_test "TARGET_PORTABLE_RUNTIME")
                    (const_int 32)
-                   (eq (symbol_ref "flag_pic") (const_int 0))
+                   (not (match_test "flag_pic"))
                    (const_int 28)]
                  (const_int 36))
             (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
@@ -8917,9 +9192,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
                    (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
                      (const_int MAX_17BIT_OFFSET))
                    (const_int 16)
-                   (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+                   (match_test "TARGET_PORTABLE_RUNTIME")
                    (const_int 32)
-                   (eq (symbol_ref "flag_pic") (const_int 0))
+                   (not (match_test "flag_pic"))
                    (const_int 28)]
                  (const_int 36)))
 
@@ -8931,9 +9206,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
                (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
                  (const_int MAX_17BIT_OFFSET))
                (const_int 12)
-               (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+               (match_test "TARGET_PORTABLE_RUNTIME")
                (const_int 28)
-               (eq (symbol_ref "flag_pic") (const_int 0))
+               (not (match_test "flag_pic"))
                (const_int 24)]
              (const_int 32)))))])
 
@@ -8945,10 +9220,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
           [(match_operand:SI 1 "register_operand" "r,r,r,r") (const_int 0)])
          (pc)
          (label_ref (match_operand 3 "" ""))))
-   (set (match_operand:SI 0 "reg_before_reload_operand" "=!r,!*f,*m,!*q")
+   (set (match_operand:SI 0 "reg_before_reload_operand" "=!r,!*f,*Q,!*q")
        (match_dup 1))]
   ""
-"* return output_movb (operands, insn, which_alternative, 1); "
+"* return pa_output_movb (operands, insn, which_alternative, 1); "
 ;; Do not expect to understand this the first time through.
 [(set_attr "type" "cbranch,multi,multi,multi")
  (set (attr "length")
@@ -8962,9 +9237,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
           (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28))
 
@@ -8978,9 +9253,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
                    (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
                      (const_int MAX_17BIT_OFFSET))
                    (const_int 16)
-                   (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+                   (match_test "TARGET_PORTABLE_RUNTIME")
                    (const_int 32)
-                   (eq (symbol_ref "flag_pic") (const_int 0))
+                   (not (match_test "flag_pic"))
                    (const_int 28)]
                  (const_int 36))
             (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
@@ -8989,9 +9264,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
                    (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
                      (const_int MAX_17BIT_OFFSET))
                    (const_int 16)
-                   (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+                   (match_test "TARGET_PORTABLE_RUNTIME")
                    (const_int 32)
-                   (eq (symbol_ref "flag_pic") (const_int 0))
+                   (not (match_test "flag_pic"))
                    (const_int 28)]
                  (const_int 36)))
 
@@ -9003,9 +9278,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
                (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
                  (const_int MAX_17BIT_OFFSET))
                (const_int 12)
-               (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+               (match_test "TARGET_PORTABLE_RUNTIME")
                (const_int 28)
-               (eq (symbol_ref "flag_pic") (const_int 0))
+               (not (match_test "flag_pic"))
                (const_int 24)]
              (const_int 32)))))])
 
@@ -9017,7 +9292,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "(reload_completed && operands[0] == operands[1]) || operands[0] == operands[2]"
   "*
 {
-  return output_parallel_addb (operands, insn);
+  return pa_output_parallel_addb (operands, insn);
 }"
 [(set_attr "type" "parallel_branch")
  (set (attr "length")
@@ -9027,9 +9302,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
           (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
@@ -9040,7 +9315,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "reload_completed"
   "*
 {
-  return output_parallel_movb (operands, insn);
+  return pa_output_parallel_movb (operands, insn);
 }"
 [(set_attr "type" "parallel_branch")
  (set (attr "length")
@@ -9050,9 +9325,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
@@ -9063,7 +9338,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "reload_completed"
   "*
 {
-  return output_parallel_movb (operands, insn);
+  return pa_output_parallel_movb (operands, insn);
 }"
 [(set_attr "type" "parallel_branch")
  (set (attr "length")
@@ -9073,9 +9348,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
@@ -9086,7 +9361,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "reload_completed"
   "*
 {
-  return output_parallel_movb (operands, insn);
+  return pa_output_parallel_movb (operands, insn);
 }"
 [(set_attr "type" "parallel_branch")
  (set (attr "length")
@@ -9096,9 +9371,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
@@ -9109,7 +9384,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "reload_completed"
   "*
 {
-  return output_parallel_movb (operands, insn);
+  return pa_output_parallel_movb (operands, insn);
 }"
 [(set_attr "type" "parallel_branch")
  (set (attr "length")
@@ -9119,9 +9394,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
               (const_int MAX_17BIT_OFFSET))
           (const_int 8)
-          (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+          (match_test "TARGET_PORTABLE_RUNTIME")
           (const_int 24)
-          (eq (symbol_ref "flag_pic") (const_int 0))
+          (not (match_test "flag_pic"))
           (const_int 20)]
          (const_int 28)))])
 
@@ -9133,7 +9408,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
        (plus (match_operand 4 "register_operand" "f")
              (match_operand 5 "register_operand" "f")))]
   "TARGET_PA_11 && ! TARGET_SOFT_FLOAT
-   && reload_completed && fmpyaddoperands (operands)"
+   && reload_completed && pa_fmpyaddoperands (operands)"
   "*
 {
   if (GET_MODE (operands[0]) == DFmode)
@@ -9162,7 +9437,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
        (mult (match_operand 1 "register_operand" "f")
              (match_operand 2 "register_operand" "f")))]
   "TARGET_PA_11 && ! TARGET_SOFT_FLOAT
-   && reload_completed && fmpyaddoperands (operands)"
+   && reload_completed && pa_fmpyaddoperands (operands)"
   "*
 {
   if (GET_MODE (operands[0]) == DFmode)
@@ -9191,7 +9466,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
        (minus (match_operand 4 "register_operand" "f")
               (match_operand 5 "register_operand" "f")))]
   "TARGET_PA_11 && ! TARGET_SOFT_FLOAT
-   && reload_completed && fmpysuboperands (operands)"
+   && reload_completed && pa_fmpysuboperands (operands)"
   "*
 {
   if (GET_MODE (operands[0]) == DFmode)
@@ -9210,7 +9485,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
        (mult (match_operand 1 "register_operand" "f")
              (match_operand 2 "register_operand" "f")))]
   "TARGET_PA_11 && ! TARGET_SOFT_FLOAT
-   && reload_completed && fmpysuboperands (operands)"
+   && reload_completed && pa_fmpysuboperands (operands)"
   "*
 {
   if (GET_MODE (operands[0]) == DFmode)
@@ -9388,7 +9663,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 
       emit_library_call_value (canonicalize_funcptr_for_compare_libfunc,
                               operands[0], LCT_NORMAL, Pmode,
-                              1, operands[1], Pmode);
+                              operands[1], Pmode);
       DONE;
     }
 
@@ -9436,14 +9711,15 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   output_asm_insn (\"{comb|cmpb},<<,n %%r26,%%r31,.+%1\", xoperands);
 
   /* Finally, call $$sh_func_adrs to extract the function's real add24.  */
-  return output_millicode_call (insn,
-                               gen_rtx_SYMBOL_REF (SImode,
-                                                   \"$$sh_func_adrs\"));
+  return pa_output_millicode_call (insn,
+                                  gen_rtx_SYMBOL_REF (SImode,
+                                                      \"$$sh_func_adrs\"));
 }"
-  [(set_attr "type" "multi")
+  [(set_attr "type" "sh_func_adrs")
    (set (attr "length")
-       (plus (symbol_ref "attr_length_millicode_call (insn)")
-             (const_int 20)))])
+       (cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 28)]
+             (plus (symbol_ref "pa_attr_length_millicode_call (insn)")
+                   (const_int 20))))])
 
 ;; On the PA, the PIC register is call clobbered, so it must
 ;; be saved & restored around calls by the caller.  If the call
@@ -9513,7 +9789,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
     {
       addr = gen_rtx_PLUS (word_mode, stack_pointer_rtx,
                           GEN_INT (TARGET_64BIT ? -8 : -4));
-      emit_move_insn (gen_rtx_MEM (word_mode, addr), frame_pointer_rtx);
+      emit_move_insn (gen_rtx_MEM (word_mode, addr), hard_frame_pointer_rtx);
     }
   if (!TARGET_64BIT && flag_pic)
     {
@@ -9529,90 +9805,39 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
    (match_operand 2 "const_int_operand" "")]
   "TARGET_PA_20"
 {
-  int locality = INTVAL (operands[2]);
-
-  gcc_assert (locality >= 0 && locality <= 3);
-
-  /* Change operand[0] to a MEM as we don't have the infrastructure
-     to output all the supported address modes for ldw/ldd when we use
-     the address directly.  However, we do have it for MEMs.  */
-  operands[0] = gen_rtx_MEM (QImode, operands[0]);
-
-  /* If the address isn't valid for the prefetch, replace it.  */
-  if (locality)
-    {
-      if (!prefetch_nocc_operand (operands[0], QImode))
-       operands[0]
-         = replace_equiv_address (operands[0],
-                                  copy_to_mode_reg (Pmode,
-                                                    XEXP (operands[0], 0)));
-      emit_insn (gen_prefetch_nocc (operands[0], operands[1], operands[2]));
-    }
-  else
-    {
-      if (!prefetch_cc_operand (operands[0], QImode))
-       operands[0]
-         = replace_equiv_address (operands[0],
-                                  copy_to_mode_reg (Pmode,
-                                                    XEXP (operands[0], 0)));
-      emit_insn (gen_prefetch_cc (operands[0], operands[1], operands[2]));
-    }
+  operands[0] = copy_addr_to_reg (operands[0]);
+  emit_insn (gen_prefetch_20 (operands[0], operands[1], operands[2]));
   DONE;
 })
 
-(define_insn "prefetch_cc"
-  [(prefetch (match_operand:QI 0 "prefetch_cc_operand" "RW")
+(define_insn "prefetch_20"
+  [(prefetch (match_operand 0 "pmode_register_operand" "r")
             (match_operand:SI 1 "const_int_operand" "n")
             (match_operand:SI 2 "const_int_operand" "n"))]
-  "TARGET_PA_20 && operands[2] == const0_rtx"
+  "TARGET_PA_20"
 {
-  /* The SL cache-control completor indicates good spatial locality but
+  /* The SL cache-control completer indicates good spatial locality but
      poor temporal locality.  The ldw instruction with a target of general
      register 0 prefetches a cache line for a read.  The ldd instruction
      prefetches a cache line for a write.  */
-  static const char * const instr[2] = {
-    "ldw%M0,sl %0,%%r0",
-    "ldd%M0,sl %0,%%r0"
-  };
-  int read_or_write = INTVAL (operands[1]);
-
-  gcc_assert (read_or_write >= 0 && read_or_write <= 1);
-
-  return instr [read_or_write];
-}
-  [(set_attr "type" "load")
-   (set_attr "length" "4")])
-
-(define_insn "prefetch_nocc"
-  [(prefetch (match_operand:QI 0 "prefetch_nocc_operand" "A,RQ")
-            (match_operand:SI 1 "const_int_operand" "n,n")
-            (match_operand:SI 2 "const_int_operand" "n,n"))]
-  "TARGET_PA_20 && operands[2] != const0_rtx"
-{
-  /* The ldw instruction with a target of general register 0 prefetches
-     a cache line for a read.  The ldd instruction prefetches a cache line
-     for a write.  */
   static const char * const instr[2][2] = {
     {
-      "ldw RT'%A0,%%r0",
-      "ldd RT'%A0,%%r0",
+      "ldw,sl 0(%0),%%r0",
+      "ldd,sl 0(%0),%%r0"
     },
     {
-      "ldw%M0 %0,%%r0",
-      "ldd%M0 %0,%%r0",
+      "ldw 0(%0),%%r0",
+      "ldd 0(%0),%%r0"
     }
   };
-  int read_or_write = INTVAL (operands[1]);
+  int read_or_write = INTVAL (operands[1]) == 0 ? 0 : 1;
+  int locality = INTVAL (operands[2]) == 0 ? 0 : 1;
 
-  gcc_assert (which_alternative == 0 || which_alternative == 1);
-  gcc_assert (read_or_write >= 0 && read_or_write <= 1);
-
-  return instr [which_alternative][read_or_write];
+  return instr [locality][read_or_write];
 }
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
-
 ;; TLS Support
 (define_insn "tgd_load"
  [(set (match_operand:SI 0 "register_operand" "=r")
@@ -9724,3 +9949,192 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "addil LR'%1-$tls_leoff$,%2\;ldo RR'%1-$tls_leoff$(%%r1),%0"
   [(set_attr "type" "multi")
    (set_attr "length" "8")])
+
+;; Atomic instructions
+
+;; All memory loads and stores access storage atomically except
+;; for one exception.  The STORE BYTES, STORE DOUBLE BYTES, and
+;; doubleword loads and stores are not guaranteed to be atomic
+;; when referencing the I/O address space.
+
+;; These patterns are at the bottom so the non atomic versions are preferred.
+
+(define_expand "atomic_storeqi"
+  [(match_operand:QI 0 "memory_operand")                ;; memory
+   (match_operand:QI 1 "register_operand")              ;; val out
+   (match_operand:SI 2 "const_int_operand")]            ;; model
+  ""
+{
+  if (TARGET_SYNC_LIBCALL)
+    {
+      rtx mem = operands[0];
+      rtx val = operands[1];
+      if (pa_maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val))
+       DONE;
+    }
+  FAIL;
+})
+
+;; Implement atomic HImode stores using exchange.
+
+(define_expand "atomic_storehi"
+  [(match_operand:HI 0 "memory_operand")                ;; memory
+   (match_operand:HI 1 "register_operand")              ;; val out
+   (match_operand:SI 2 "const_int_operand")]            ;; model
+  ""
+{
+  if (TARGET_SYNC_LIBCALL)
+    {
+      rtx mem = operands[0];
+      rtx val = operands[1];
+      if (pa_maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val))
+       DONE;
+    }
+  FAIL;
+})
+
+;; Implement atomic SImode store using exchange.
+
+(define_expand "atomic_storesi"
+  [(match_operand:SI 0 "memory_operand")                ;; memory
+   (match_operand:SI 1 "register_operand")              ;; val out
+   (match_operand:SI 2 "const_int_operand")]            ;; model
+  ""
+{
+  if (TARGET_SYNC_LIBCALL)
+    {
+      rtx mem = operands[0];
+      rtx val = operands[1];
+      if (pa_maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val))
+       DONE;
+    }
+  FAIL;
+})
+
+;; Implement atomic DImode load.
+
+(define_expand "atomic_loaddi"
+  [(match_operand:DI 0 "register_operand")              ;; val out
+   (match_operand:DI 1 "memory_operand")                ;; memory
+   (match_operand:SI 2 "const_int_operand")]            ;; model
+  ""
+{
+  enum memmodel model;
+
+  if (TARGET_64BIT || TARGET_DISABLE_FPREGS || TARGET_SOFT_FLOAT)
+    FAIL;
+
+  model = memmodel_from_int (INTVAL (operands[2]));
+  operands[1] = force_reg (SImode, XEXP (operands[1], 0));
+  if (is_mm_seq_cst (model))
+    expand_mem_thread_fence (model);
+  emit_insn (gen_atomic_loaddi_1 (operands[0], operands[1]));
+  expand_mem_thread_fence (model);
+  DONE;
+})
+
+(define_insn "atomic_loaddi_1"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (mem:DI (match_operand:SI 1 "register_operand" "r")))
+   (clobber (match_scratch:DI 2 "=f"))]
+  "!TARGET_64BIT && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT"
+  "{fldds|fldd} 0(%1),%2\n\t{fstds|fstd} %2,-16(%%sp)\n\t{ldws|ldw} -16(%%sp),%0\n\t{ldws|ldw} -12(%%sp),%R0"
+  [(set_attr "type" "move")
+   (set_attr "length" "16")])
+
+;; Implement atomic DImode store.
+
+(define_expand "atomic_storedi"
+  [(match_operand:DI 0 "memory_operand")                ;; memory
+   (match_operand:DI 1 "reg_or_cint_move_operand")      ;; val out
+   (match_operand:SI 2 "const_int_operand")]            ;; model
+  ""
+{
+  enum memmodel model;
+
+  if (TARGET_SYNC_LIBCALL)
+    {
+      rtx mem = operands[0];
+      rtx val = operands[1];
+      if (pa_maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val))
+       DONE;
+    }
+
+  if (TARGET_64BIT || TARGET_DISABLE_FPREGS || TARGET_SOFT_FLOAT)
+    FAIL;
+
+  model = memmodel_from_int (INTVAL (operands[2]));
+  operands[0] = force_reg (SImode, XEXP (operands[0], 0));
+  if (operands[1] != CONST0_RTX (DImode))
+    operands[1] = force_reg (DImode, operands[1]);
+  expand_mem_thread_fence (model);
+  emit_insn (gen_atomic_storedi_1 (operands[0], operands[1]));
+  if (is_mm_seq_cst (model))
+    expand_mem_thread_fence (model);
+  DONE;
+})
+
+(define_insn "atomic_storedi_1"
+  [(set (mem:DI (match_operand:SI 0 "register_operand" "r,r"))
+        (match_operand:DI 1 "reg_or_0_operand" "M,r"))
+   (clobber (match_scratch:DI 2 "=X,f"))]
+  "!TARGET_64BIT && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT"
+  "@
+   {fstds|fstd} %%fr0,0(%0)
+   {stws|stw} %1,-16(%%sp)\n\t{stws|stw} %R1,-12(%%sp)\n\t{fldds|fldd} -16(%%sp),%2\n\t{fstds|fstd} %2,0(%0)"
+  [(set_attr "type" "move,move")
+   (set_attr "length" "4,16")])
+
+;; PA 2.0 hardware supports out-of-order execution of loads and stores, so
+;; we need memory barriers to enforce program order for memory references
+;; when the TLB and PSW O bits are not set.  We assume all PA 2.0 systems
+;; are weakly ordered since neither HP-UX or Linux set the PSW O bit.  Since
+;; we want PA 1.x code to be PA 2.0 compatible, we also need barriers when
+;; generating PA 1.x code even though all PA 1.x systems are strongly ordered.
+
+;; When barriers are needed, we use a strongly ordered ldcw instruction as
+;; the barrier.  Most PA 2.0 targets are cache coherent.  In that case, we
+;; can use the coherent cache control hint and avoid aligning the ldcw
+;; address.  In spite of its description, it is not clear that the sync
+;; instruction works as a barrier.
+
+(define_expand "memory_barrier"
+  [(parallel
+     [(set (match_dup 0) (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))
+      (clobber (match_dup 1))])]
+  ""
+{
+  /* We don't need a barrier if the target uses ordered memory references.  */
+  if (TARGET_ORDERED)
+    FAIL;
+  operands[1] = gen_reg_rtx (Pmode);
+  operands[0] = gen_rtx_MEM (BLKmode, operands[1]);
+  MEM_VOLATILE_P (operands[0]) = 1;
+})
+
+(define_insn "*memory_barrier_coherent"
+  [(set (match_operand:BLK 0 "" "")
+        (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))
+   (clobber (match_operand 1 "pmode_register_operand" "=r"))]
+  "TARGET_PA_20 && TARGET_COHERENT_LDCW"
+  "ldcw,co 0(%%sp),%1"
+  [(set_attr "type" "binary")
+   (set_attr "length" "4")])
+
+(define_insn "*memory_barrier_64"
+  [(set (match_operand:BLK 0 "" "")
+        (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))
+    (clobber (match_operand 1 "pmode_register_operand" "=&r"))]
+  "TARGET_64BIT"
+  "ldo 15(%%sp),%1\n\tdepd %%r0,63,3,%1\n\tldcw 0(%1),%1"
+  [(set_attr "type" "binary")
+   (set_attr "length" "12")])
+
+(define_insn "*memory_barrier_32"
+  [(set (match_operand:BLK 0 "" "")
+        (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))
+    (clobber (match_operand 1 "pmode_register_operand" "=&r"))]
+  ""
+  "ldo 15(%%sp),%1\n\t{dep|depw} %%r0,31,3,%1\n\tldcw 0(%1),%1"
+  [(set_attr "type" "binary")
+   (set_attr "length" "12")])