gcc/ChangeLog:

        * config/loongarch/sync.md (UNSPEC_TI_FETCH_ADD): New unspec.
        (UNSPEC_TI_FETCH_SUB): Likewise.
        (UNSPEC_TI_FETCH_AND): Likewise.
        (UNSPEC_TI_FETCH_XOR): Likewise.
        (UNSPEC_TI_FETCH_OR): Likewise.
        (UNSPEC_TI_FETCH_NAND_MASK_INVERTED): Likewise.
        (ALL_SC): New define_mode_iterator.
        (_scq): New define_mode_attr.
        (atomic_fetch_nand<mode>): Accept ALL_SC instead of only GPR.
        (UNSPEC_TI_FETCH_DIRECT): New define_int_iterator.
        (UNSPEC_TI_FETCH): New define_int_iterator.
        (amop_ti_fetch): New define_int_attr.
        (size_ti_fetch): New define_int_attr.
        (atomic_fetch_<amop_ti_fetch>ti_scq): New define_insn.
        (atomic_fetch_<amop_ti_fetch>ti): New define_expand.
---
 gcc/config/loongarch/sync.md | 117 +++++++++++++++++++++++++++++++++--
 1 file changed, 111 insertions(+), 6 deletions(-)

diff --git a/gcc/config/loongarch/sync.md b/gcc/config/loongarch/sync.md
index 2624bbf51cf..2ee400e2381 100644
--- a/gcc/config/loongarch/sync.md
+++ b/gcc/config/loongarch/sync.md
@@ -30,6 +30,13 @@ (define_c_enum "unspec" [
   UNSPEC_ATOMIC_STORE
   UNSPEC_ATOMIC_LOAD
   UNSPEC_MEMORY_BARRIER
+
+  UNSPEC_TI_FETCH_ADD
+  UNSPEC_TI_FETCH_SUB
+  UNSPEC_TI_FETCH_AND
+  UNSPEC_TI_FETCH_XOR
+  UNSPEC_TI_FETCH_OR
+  UNSPEC_TI_FETCH_NAND_MASK_INVERTED
 ])
 
 (define_code_iterator any_atomic [plus ior xor and])
@@ -323,11 +330,13 @@ (define_insn "atomic_fetch_nand_mask_inverted<mode>"
   }
   [(set (attr "length") (const_int 16))])
 
+(define_mode_iterator ALL_SC [GPR (TI "TARGET_64BIT && ISA_HAS_SCQ")])
+(define_mode_attr _scq [(SI "") (DI "") (TI "_scq")])
 (define_expand "atomic_fetch_nand<mode>"
-  [(match_operand:GPR 0 "register_operand")
-   (match_operand:GPR 1 "memory_operand")
-   (match_operand:GPR 2 "reg_or_0_operand")
-   (match_operand:SI  3 "const_int_operand")]
+  [(match_operand:ALL_SC 0 "register_operand")
+   (match_operand:ALL_SC 1 "memory_operand")
+   (match_operand:ALL_SC 2 "reg_or_0_operand")
+   (match_operand:SI     3 "const_int_operand")]
   ""
   {
     /* ~(atom & mask) = (~mask) | (~atom), so we can hoist
@@ -339,8 +348,9 @@ (define_expand "atomic_fetch_nand<mode>"
                                        NULL_RTX, false));
 
     emit_insn (
-      gen_atomic_fetch_nand_mask_inverted<mode> (operands[0], operands[1],
-                                                inverted_mask));
+      gen_atomic_fetch_nand_mask_inverted<mode><_scq> (operands[0],
+                                                      operands[1],
+                                                      inverted_mask));
     DONE;
   })
 
@@ -880,6 +890,101 @@ (define_expand "atomic_exchange<mode>"
   DONE;
 })
 
+(define_int_iterator UNSPEC_TI_FETCH_DIRECT
+  [UNSPEC_TI_FETCH_ADD
+   UNSPEC_TI_FETCH_SUB
+   UNSPEC_TI_FETCH_AND
+   UNSPEC_TI_FETCH_XOR
+   UNSPEC_TI_FETCH_OR])
+(define_int_iterator UNSPEC_TI_FETCH
+  [UNSPEC_TI_FETCH_DIRECT UNSPEC_TI_FETCH_NAND_MASK_INVERTED])
+(define_int_attr amop_ti_fetch
+  [(UNSPEC_TI_FETCH_ADD "add")
+   (UNSPEC_TI_FETCH_SUB "sub")
+   (UNSPEC_TI_FETCH_AND "and")
+   (UNSPEC_TI_FETCH_XOR "xor")
+   (UNSPEC_TI_FETCH_OR "or")
+   (UNSPEC_TI_FETCH_NAND_MASK_INVERTED "nand_mask_inverted")])
+(define_int_attr size_ti_fetch
+  [(UNSPEC_TI_FETCH_ADD "36")
+   (UNSPEC_TI_FETCH_SUB "36")
+   (UNSPEC_TI_FETCH_AND "28")
+   (UNSPEC_TI_FETCH_XOR "28")
+   (UNSPEC_TI_FETCH_OR "28")
+   (UNSPEC_TI_FETCH_NAND_MASK_INVERTED "28")])
+
+(define_insn "atomic_fetch_<amop_ti_fetch>ti_scq"
+  [(set (match_operand:TI 0 "register_operand" "=&r")
+        (match_operand:TI 1 "memory_operand" "+ZB"))
+   (set (match_dup 1)
+       (unspec_volatile:TI
+         [(match_dup 0)
+          (match_operand:TI 2 "reg_or_0_operand" "rJ")]
+         UNSPEC_TI_FETCH))
+   (clobber (match_scratch:DI 3 "=&r"))
+   (clobber (match_scratch:DI 4 "=&r"))]
+  "TARGET_64BIT && ISA_HAS_SCQ"
+{
+  output_asm_insn ("1:", operands);
+  output_asm_insn ("ll.d\t%0,%1", operands);
+  if (!ISA_HAS_LD_SEQ_SA)
+    output_asm_insn ("dbar\t0x700", operands);
+  output_asm_insn ("ld.d\t%t0,%b1,8", operands);
+
+  switch (<UNSPEC_TI_FETCH>)
+    {
+    case UNSPEC_TI_FETCH_AND:
+    case UNSPEC_TI_FETCH_OR:
+    case UNSPEC_TI_FETCH_XOR:
+      output_asm_insn ("<amop_ti_fetch>\t%3,%0,%z2", operands);
+      output_asm_insn ("<amop_ti_fetch>\t%4,%t0,%t2", operands);
+      break;
+    case UNSPEC_TI_FETCH_NAND_MASK_INVERTED:
+      output_asm_insn ("orn\t%3,%z2,%0", operands);
+      output_asm_insn ("orn\t%4,%t2,%t0", operands);
+      break;
+    case UNSPEC_TI_FETCH_ADD:
+    case UNSPEC_TI_FETCH_SUB:
+      output_asm_insn ("<amop_ti_fetch>.d\t%3,%0,%z2", operands);
+
+      /* Generate carry bit.  */
+      output_asm_insn (
+       <UNSPEC_TI_FETCH> == UNSPEC_TI_FETCH_ADD ? "sltu\t%4,%3,%0"
+                                                : "sltu\t%4,%0,%3",
+       operands);
+
+      output_asm_insn ("<amop_ti_fetch>.d\t%4,%t0,%4", operands);
+      output_asm_insn ("<amop_ti_fetch>.d\t%4,%4,%t2", operands);
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  output_asm_insn ("sc.q\t%3,%4,%1", operands);
+  output_asm_insn ("beqz\t%3,1b", operands);
+
+  return "";
+}
+  [(set_attr "length" "<size_ti_fetch>")])
+
+(define_expand "atomic_fetch_<amop_ti_fetch>ti"
+  [(set (match_operand:TI 0 "register_operand" "=&r")
+        (match_operand:TI 1 "memory_operand" "+ZB"))
+   (set (match_dup 1)
+       (unspec_volatile:TI
+         [(match_dup 0)
+          (match_operand:TI 2 "reg_or_0_operand" "rJ")]
+         UNSPEC_TI_FETCH_DIRECT))
+   (match_operand:SI    3 "const_int_operand")] ;; model
+  "TARGET_64BIT && ISA_HAS_SCQ"
+{
+  /* Model is ignored as sc.q implies a full barrier.  */
+  emit_insn (gen_atomic_fetch_<amop_ti_fetch>ti_scq (operands[0],
+                                                    operands[1],
+                                                    operands[2]));
+  DONE;
+})
+
 (define_insn "atomic_fetch_add<mode>_short"
   [(set (match_operand:SHORT 0 "register_operand" "=&r")
        (match_operand:SHORT 1 "memory_operand" "+ZB"))
-- 
2.48.1

Reply via email to