]> 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 241d312fb1a4928410cc19ffc8a2b340d8829078..1b4a5247370e3683f28ca989edded3141f3010ed 100644 (file)
@@ -1,5 +1,5 @@
 ;;- Machine description for HP PA-RISC architecture for GCC compiler
-;;   Copyright (C) 1992-2015 Free Software Foundation, Inc.
+;;   Copyright (C) 1992-2019 Free Software Foundation, Inc.
 ;;   Contributed by the Center for Software Science at the University
 ;;   of Utah.
 
@@ -84,6 +84,7 @@
    UNSPEC_TLSGD_PIC
    UNSPEC_TLSLDM_PIC
    UNSPEC_TLSIE_PIC
+   UNSPEC_MEMORY_BARRIER
   ])
 
 ;; UNSPEC_VOLATILE:
 [(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"
 
   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")
+       (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "r")
+                         (match_operand:SI 3 "mem_shadd_operand" ""))
+                (match_operand:SI 1 "register_operand" "r")))]
+  ""
+  "*
+{
+  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")
   [(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 "mem_shadd_operand" ""))
+                (match_operand:DI 1 "register_operand" "r")))]
+  "TARGET_64BIT"
+  "*
+{
+  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")])
+
 (define_expand "ashlsi3"
   [(set (match_operand:SI 0 "register_operand" "")
        (ashift:SI (match_operand:SI 1 "lhs_lshift_operand" "")
@@ -6973,7 +7069,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
       op = XEXP (operands[0], 0);
 
       /* Generate indirect long calls to non-local functions. */
-      if (!TARGET_64BIT && TARGET_LONG_CALLS && GET_CODE (op) == SYMBOL_REF)
+      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)))
@@ -7273,7 +7369,6 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "TARGET_64BIT"
   "*
 {
-  pa_output_arg_descriptor (insn);
   return pa_output_call (insn, operands[0], 0);
 }"
   [(set_attr "type" "call")
@@ -7476,7 +7571,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
            call_powf = true;
 
          /* Generate indirect long calls to non-local functions. */
-         else if (!TARGET_64BIT && TARGET_LONG_CALLS)
+         else if (TARGET_LONG_CALLS)
            {
              tree call_decl = SYMBOL_REF_DECL (op);
              if (!(call_decl && targetm.binds_local_p (call_decl)))
@@ -7883,7 +7978,6 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "TARGET_64BIT"
   "*
 {
-  pa_output_arg_descriptor (insn);
   return pa_output_call (insn, operands[1], 0);
 }"
   [(set_attr "type" "call")
@@ -7978,7 +8072,6 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "TARGET_64BIT && TARGET_HPUX"
   "*
 {
-  pa_output_arg_descriptor (insn);
   return pa_output_call (insn, operands[1], 0);
 }"
   [(set_attr "type" "call")
@@ -8092,7 +8185,6 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   [(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))
    (clobber (match_operand 3))
    (use (reg:DI 27))
@@ -8114,7 +8206,6 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   [(parallel [(set (match_operand 0 "" "")
                   (call (mem:SI (match_operand:DI 1 "register_operand" ""))
                         (match_operand 2 "" "")))
-             (clobber (reg:DI 1))
              (clobber (reg:DI 2))
              (clobber (match_operand 3))
              (use (reg:DI 27))
@@ -8126,7 +8217,6 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
    (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))
@@ -8137,7 +8227,6 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   [(parallel [(set (match_operand 0 "" "")
                   (call (mem:SI (match_operand:DI 1 "register_operand" ""))
                         (match_operand 2 "" "")))
-             (clobber (reg:DI 1))
              (clobber (reg:DI 2))
              (clobber (match_operand 3))
              (use (reg:DI 27))
@@ -8148,7 +8237,6 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
    (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))
@@ -8160,7 +8248,6 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   [(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 (reg:DI 27))
    (use (reg:DI 29))
@@ -8175,6 +8262,170 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
        (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))]
+  "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:DI 2))
+             (clobber (match_operand 3))
+             (use (reg:DI 27))
+             (use (reg:DI 29))])]
+  "TARGET_64BIT && reload_completed"
+  [(set (match_dup 3) (reg:DI 27))
+   (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))])
+   (set (reg:DI 27) (match_dup 3))]
+  "")
+
+(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))]
+  "TARGET_64BIT"
+  "{bl|b,l} %0,%%r2\;ldo %2-.-4(%%r2),%%r25"
+  [(set_attr "type" "multi")
+   (set_attr "length" "8")])
+
 ;; Call subroutine returning any type.
 
 (define_expand "untyped_call"
@@ -8280,7 +8531,6 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "TARGET_64BIT"
   "*
 {
-  pa_output_arg_descriptor (insn);
   return pa_output_call (insn, operands[0], 1);
 }"
   [(set_attr "type" "sibcall")
@@ -8369,7 +8619,6 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   "TARGET_64BIT"
   "*
 {
-  pa_output_arg_descriptor (insn);
   return pa_output_call (insn, operands[1], 1);
 }"
   [(set_attr "type" "sibcall")
@@ -9413,7 +9662,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;
     }
 
@@ -9707,14 +9956,8 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 ;; doubleword loads and stores are not guaranteed to be atomic
 ;; when referencing the I/O address space.
 
-;; The kernel cmpxchg operation on linux is not atomic with respect to
-;; memory stores on SMP machines, so we must do stores using a cmpxchg
-;; operation.
-
 ;; These patterns are at the bottom so the non atomic versions are preferred.
 
-;; Implement atomic QImode store using exchange.
-
 (define_expand "atomic_storeqi"
   [(match_operand:QI 0 "memory_operand")                ;; memory
    (match_operand:QI 1 "register_operand")              ;; val out
@@ -9767,25 +10010,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   FAIL;
 })
 
-;; Implement atomic SFmode store using exchange.
-
-(define_expand "atomic_storesf"
-  [(match_operand:SF 0 "memory_operand")                ;; memory
-   (match_operand:SF 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 using 64-bit floating point load.
+;; Implement atomic DImode load.
 
 (define_expand "atomic_loaddi"
   [(match_operand:DI 0 "register_operand")              ;; val out
@@ -9800,29 +10025,27 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 
   model = memmodel_from_int (INTVAL (operands[2]));
   operands[1] = force_reg (SImode, XEXP (operands[1], 0));
-  expand_mem_thread_fence (model);
-  emit_insn (gen_atomic_loaddi_1 (operands[0], operands[1]));
   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" "=f,r")
-        (mem:DI (match_operand:SI 1 "register_operand" "r,r")))
-   (clobber (match_scratch:DI 2 "=X,f"))]
+  [(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),%0
-   {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,move")
-   (set_attr "length" "4,16")])
+  "{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 "register_operand")              ;; val out
+   (match_operand:DI 1 "reg_or_cint_move_operand")      ;; val out
    (match_operand:SI 2 "const_int_operand")]            ;; model
   ""
 {
@@ -9841,6 +10064,8 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 
   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))
@@ -9850,87 +10075,33 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 
 (define_insn "atomic_storedi_1"
   [(set (mem:DI (match_operand:SI 0 "register_operand" "r,r"))
-        (match_operand:DI 1 "register_operand" "f,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 && !TARGET_SYNC_LIBCALL"
+  "!TARGET_64BIT && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT"
   "@
-   {fstds|fstd} %1,0(%0)
+   {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")])
 
-;; Implement atomic DFmode load using 64-bit floating point load.
+;; PA 2.0 hardware supports out-of-order execution of loads and stores, so
+;; we need a memory barrier to enforce program order for memory references.
+;; Since we want PA 1.x code to be PA 2.0 compatible, we also need the
+;; barrier when generating PA 1.x code.
 
-(define_expand "atomic_loaddf"
-  [(match_operand:DF 0 "register_operand")              ;; val out
-   (match_operand:DF 1 "memory_operand")                ;; memory
-   (match_operand:SI 2 "const_int_operand")]            ;; model
+(define_expand "memory_barrier"
+  [(set (match_dup 0)
+        (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))]
   ""
 {
-  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));
-  expand_mem_thread_fence (model);
-  emit_insn (gen_atomic_loaddf_1 (operands[0], operands[1]));
-  if (is_mm_seq_cst (model))
-    expand_mem_thread_fence (model);
-  DONE;
+  operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+  MEM_VOLATILE_P (operands[0]) = 1;
 })
 
-(define_insn "atomic_loaddf_1"
-  [(set (match_operand:DF 0 "register_operand" "=f,r")
-        (mem:DF (match_operand:SI 1 "register_operand" "r,r")))
-   (clobber (match_scratch:DF 2 "=X,f"))]
-  "!TARGET_64BIT && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT"
-  "@
-   {fldds|fldd} 0(%1),%0
-   {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,move")
-   (set_attr "length" "4,16")])
-
-;; Implement atomic DFmode store using 64-bit floating point store.
-
-(define_expand "atomic_storedf"
-  [(match_operand:DF 0 "memory_operand")                ;; memory
-   (match_operand:DF 1 "register_operand")              ;; val out
-   (match_operand:SI 2 "const_int_operand")]            ;; model
+(define_insn "*memory_barrier"
+  [(set (match_operand:BLK 0 "" "")
+        (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))]
   ""
-{
-  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));
-  expand_mem_thread_fence (model);
-  emit_insn (gen_atomic_storedf_1 (operands[0], operands[1]));
-  if (is_mm_seq_cst (model))
-    expand_mem_thread_fence (model);
-  DONE;
-})
-
-(define_insn "atomic_storedf_1"
-  [(set (mem:DF (match_operand:SI 0 "register_operand" "r,r"))
-        (match_operand:DF 1 "register_operand" "f,r"))
-   (clobber (match_scratch:DF 2 "=X,f"))]
-  "!TARGET_64BIT && !TARGET_DISABLE_FPREGS
-   && !TARGET_SOFT_FLOAT && !TARGET_SYNC_LIBCALL"
-  "@
-   {fstds|fstd} %1,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")])
+  "sync"
+  [(set_attr "type" "binary")
+   (set_attr "length" "4")])