This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

atomic char/short operations for alpha


I thought I'd committed this ages ago, but apparently not.
It still checks ok.


r~


        * config/alpha/alpha.c (emit_insxl, alpha_expand_compare_and_swap_12,
        alpha_split_compare_and_swap_12, alpha_expand_lock_test_and_set_12,
        alpha_split_lock_test_and_set_12): New functions.
        * config/alpha/alpha-protos.h: Update.
        * config/alpha/alpha.md (UNSPEC_MB, UNSPEC_ATOMIC,
        UNSPEC_CMPXCHG, UNSPEC_XCHG): Rename from UNSPECV_FOO.
        * config/alpha/sync.md (I12MODE): New.
        (memory_barrier, mb_internal): Use unspec instead of unspec_volatile.
        (sync_<fetchop_name><I48MODE>): Likewise.
        (sync_nand<I48MODE>): Likewise.
        (sync_old_<fetchop_name><I48MODE>): Likewise.
        (sync_new_<fetchop_name><I48MODE>): Likewise.
        (sync_old_nand<I48MODE>, sync_new_nand<I48MODE>): Likewise.
        (sync_compare_and_swap<I48MODE>): Likewise.
        (sync_lock_test_and_set<I48MODE>): Likewise.
        (sync_compare_and_swap<I12MODE>): New.
        (sync_compare_and_swap<I12MODE>_1): New.
        (sync_lock_test_and_set<I12MODE>): New.
        (sync_lock_test_and_set<I12MODE>_1): New.

        * lib/target-supports.exp (check_effective_target_sync_char_short):
        Add alpha.

Index: gcc/config/alpha/alpha-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha-protos.h,v
retrieving revision 1.64
diff -u -p -d -r1.64 alpha-protos.h
--- gcc/config/alpha/alpha-protos.h	25 Jun 2005 01:20:45 -0000	1.64
+++ gcc/config/alpha/alpha-protos.h	9 Jul 2005 18:16:46 -0000
@@ -103,7 +103,13 @@ extern void alpha_emit_xfloating_arith (
 extern void alpha_emit_xfloating_cvt (enum rtx_code, rtx[]);
 extern void alpha_split_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
 extern void alpha_split_compare_and_swap (rtx, rtx, rtx, rtx, rtx);
+extern void alpha_expand_compare_and_swap_12 (rtx, rtx, rtx, rtx);
+extern void alpha_split_compare_and_swap_12 (enum machine_mode, rtx, rtx,
+					     rtx, rtx, rtx, rtx, rtx);
 extern void alpha_split_lock_test_and_set (rtx, rtx, rtx, rtx);
+extern void alpha_expand_lock_test_and_set_12 (rtx, rtx, rtx);
+extern void alpha_split_lock_test_and_set_12 (enum machine_mode, rtx, rtx,
+					      rtx, rtx, rtx);
 #endif
 
 extern rtx alpha_need_linkage (const char *, int);
Index: gcc/config/alpha/alpha.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.c,v
retrieving revision 1.430
diff -u -p -d -r1.430 alpha.c
--- gcc/config/alpha/alpha.c	2 Jul 2005 21:49:02 -0000	1.430
+++ gcc/config/alpha/alpha.c	9 Jul 2005 18:16:48 -0000
@@ -4453,6 +4453,34 @@ emit_store_conditional (enum machine_mod
   emit_insn (fn (res, mem, val));
 }
 
+/* A subroutine of the atomic operation splitters.  Emit an insxl
+   instruction in MODE.  */
+
+static rtx
+emit_insxl (enum machine_mode mode, rtx op1, rtx op2)
+{
+  rtx ret = gen_reg_rtx (DImode);
+  rtx (*fn) (rtx, rtx, rtx);
+
+  if (WORDS_BIG_ENDIAN)
+    {
+      if (mode == QImode)
+	fn = gen_insbl_be;
+      else
+	fn = gen_inswl_be;
+    }
+  else
+    {
+      if (mode == QImode)
+	fn = gen_insbl_le;
+      else
+	fn = gen_inswl_le;
+    }
+  emit_insn (fn (ret, op1, op2));
+
+  return ret;
+}
+
 /* Expand an an atomic fetch-and-operate pattern.  CODE is the binary operation
    to perform.  MEM is the memory on which to operate.  VAL is the second 
    operand of the binary operator.  BEFORE and AFTER are optional locations to
@@ -4530,6 +4558,79 @@ alpha_split_compare_and_swap (rtx retval
   emit_label (XEXP (label2, 0));
 }
 
+void
+alpha_expand_compare_and_swap_12 (rtx dst, rtx mem, rtx oldval, rtx newval)
+{
+  enum machine_mode mode = GET_MODE (mem);
+  rtx addr, align, wdst;
+  rtx (*fn5) (rtx, rtx, rtx, rtx, rtx);
+
+  addr = force_reg (DImode, XEXP (mem, 0));
+  align = expand_simple_binop (Pmode, AND, addr, GEN_INT (-8),
+			       NULL_RTX, 1, OPTAB_DIRECT);
+
+  oldval = convert_modes (DImode, mode, oldval, 1);
+  newval = emit_insxl (mode, newval, addr);
+
+  wdst = gen_reg_rtx (DImode);
+  if (mode == QImode)
+    fn5 = gen_sync_compare_and_swapqi_1;
+  else
+    fn5 = gen_sync_compare_and_swaphi_1;
+  emit_insn (fn5 (wdst, addr, oldval, newval, align));
+
+  emit_move_insn (dst, gen_lowpart (mode, wdst));
+}
+
+void
+alpha_split_compare_and_swap_12 (enum machine_mode mode, rtx dest, rtx addr,
+				 rtx oldval, rtx newval, rtx align,
+				 rtx scratch, rtx cond)
+{
+  rtx label1, label2, mem, width, mask, x;
+
+  mem = gen_rtx_MEM (DImode, align);
+  MEM_VOLATILE_P (mem) = 1;
+
+  emit_insn (gen_memory_barrier ());
+  label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
+  label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
+  emit_label (XEXP (label1, 0));
+
+  emit_load_locked (DImode, scratch, mem);
+  
+  width = GEN_INT (GET_MODE_BITSIZE (mode));
+  mask = GEN_INT (mode == QImode ? 0xff : 0xffff);
+  if (WORDS_BIG_ENDIAN)
+    emit_insn (gen_extxl_be (dest, scratch, width, addr));
+  else
+    emit_insn (gen_extxl_le (dest, scratch, width, addr));
+
+  if (oldval == const0_rtx)
+    x = gen_rtx_NE (DImode, dest, const0_rtx);
+  else
+    {
+      x = gen_rtx_EQ (DImode, dest, oldval);
+      emit_insn (gen_rtx_SET (VOIDmode, cond, x));
+      x = gen_rtx_EQ (DImode, cond, const0_rtx);
+    }
+  emit_unlikely_jump (x, label2);
+
+  if (WORDS_BIG_ENDIAN)
+    emit_insn (gen_mskxl_be (scratch, scratch, mask, addr));
+  else
+    emit_insn (gen_mskxl_le (scratch, scratch, mask, addr));
+  emit_insn (gen_iordi3 (scratch, scratch, newval));
+
+  emit_store_conditional (DImode, scratch, mem, scratch);
+
+  x = gen_rtx_EQ (DImode, scratch, const0_rtx);
+  emit_unlikely_jump (x, label1);
+
+  emit_insn (gen_memory_barrier ());
+  emit_label (XEXP (label2, 0));
+}
+
 /* Expand an atomic exchange operation.  */
 
 void
@@ -4550,6 +4651,68 @@ alpha_split_lock_test_and_set (rtx retva
   x = gen_rtx_EQ (DImode, cond, const0_rtx);
   emit_unlikely_jump (x, label);
 }
+
+void
+alpha_expand_lock_test_and_set_12 (rtx dst, rtx mem, rtx val)
+{
+  enum machine_mode mode = GET_MODE (mem);
+  rtx addr, align, wdst;
+  rtx (*fn4) (rtx, rtx, rtx, rtx);
+
+  /* Force the address into a register.  */
+  addr = force_reg (DImode, XEXP (mem, 0));
+
+  /* Align it to a multiple of 8.  */
+  align = expand_simple_binop (Pmode, AND, addr, GEN_INT (-8),
+			       NULL_RTX, 1, OPTAB_DIRECT);
+
+  /* Insert val into the correct byte location within the word.  */
+  val = emit_insxl (mode, val, addr);
+
+  wdst = gen_reg_rtx (DImode);
+  if (mode == QImode)
+    fn4 = gen_sync_lock_test_and_setqi_1;
+  else
+    fn4 = gen_sync_lock_test_and_sethi_1;
+  emit_insn (fn4 (wdst, addr, val, align));
+
+  emit_move_insn (dst, gen_lowpart (mode, wdst));
+}
+
+void
+alpha_split_lock_test_and_set_12 (enum machine_mode mode, rtx dest, rtx addr,
+				  rtx val, rtx align, rtx scratch)
+{
+  rtx label, mem, width, mask, x;
+
+  mem = gen_rtx_MEM (DImode, align);
+  MEM_VOLATILE_P (mem) = 1;
+
+  emit_insn (gen_memory_barrier ());
+  label = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
+  emit_label (XEXP (label, 0));
+
+  emit_load_locked (DImode, scratch, mem);
+  
+  width = GEN_INT (GET_MODE_BITSIZE (mode));
+  mask = GEN_INT (mode == QImode ? 0xff : 0xffff);
+  if (WORDS_BIG_ENDIAN)
+    {
+      emit_insn (gen_extxl_be (dest, scratch, width, addr));
+      emit_insn (gen_mskxl_be (scratch, scratch, mask, addr));
+    }
+  else
+    {
+      emit_insn (gen_extxl_le (dest, scratch, width, addr));
+      emit_insn (gen_mskxl_le (scratch, scratch, mask, addr));
+    }
+  emit_insn (gen_iordi3 (scratch, scratch, val));
+
+  emit_store_conditional (DImode, scratch, mem, scratch);
+
+  x = gen_rtx_EQ (DImode, scratch, const0_rtx);
+  emit_unlikely_jump (x, label);
+}
 
 /* Adjust the cost of a scheduling dependency.  Return the new cost of
    a dependency LINK or INSN on DEP_INSN.  COST is the current cost.  */
Index: gcc/config/alpha/alpha.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.md,v
retrieving revision 1.243
diff -u -p -d -r1.243 alpha.md
--- gcc/config/alpha/alpha.md	29 Jun 2005 18:22:06 -0000	1.243
+++ gcc/config/alpha/alpha.md	9 Jul 2005 18:16:49 -0000
@@ -56,6 +56,12 @@
    (UNSPEC_IMPLVER	25)
    (UNSPEC_PERR		26)
    (UNSPEC_COPYSIGN     27)
+
+   ;; Atomic operations
+   (UNSPEC_MB		28)
+   (UNSPEC_ATOMIC	31)
+   (UNSPEC_CMPXCHG	32)
+   (UNSPEC_XCHG		33)
   ])
 
 ;; UNSPEC_VOLATILE:
@@ -76,12 +82,8 @@
    (UNSPECV_SET_TP	12)
    (UNSPECV_RPCC	13)
    (UNSPECV_SETJMPR_ER	14)	; builtin_setjmp_receiver fragment
-   (UNSPECV_MB		15)
-   (UNSPECV_LL		16)	; load-locked
-   (UNSPECV_SC		17)	; store-conditional
-   (UNSPECV_ATOMIC	18)
-   (UNSPECV_CMPXCHG	19)
-   (UNSPECV_XCHG	20)
+   (UNSPECV_LL		15)	; load-locked
+   (UNSPECV_SC		16)	; store-conditional
   ])
 
 ;; Where necessary, the suffixes _le and _be are used to distinguish between
Index: gcc/config/alpha/sync.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/sync.md,v
retrieving revision 1.5
diff -u -p -d -r1.5 sync.md
--- gcc/config/alpha/sync.md	25 Jun 2005 01:20:48 -0000	1.5
+++ gcc/config/alpha/sync.md	9 Jul 2005 18:16:50 -0000
@@ -19,6 +19,7 @@
 ;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
 ;; Boston, MA 02110-1301, USA.
 
+(define_mode_macro I12MODE [QI HI])
 (define_mode_macro I48MODE [SI DI])
 (define_mode_attr modesuffix [(SI "l") (DI "q")])
 
@@ -34,7 +35,7 @@
 
 (define_expand "memory_barrier"
   [(set (mem:BLK (match_dup 0))
-	(unspec_volatile:BLK [(mem:BLK (match_dup 0))] UNSPECV_MB))]
+	(unspec:BLK [(mem:BLK (match_dup 0))] UNSPEC_MB))]
   ""
 {
   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode));
@@ -43,7 +44,7 @@
 
 (define_insn "*mb_internal"
   [(set (match_operand:BLK 0 "" "")
-	(unspec_volatile:BLK [(match_operand:BLK 1 "" "")] UNSPECV_MB))]
+	(unspec:BLK [(match_operand:BLK 1 "" "")] UNSPEC_MB))]
   ""
   "mb"
   [(set_attr "type" "mb")])
@@ -75,10 +76,10 @@
 
 (define_insn_and_split "sync_<fetchop_name><mode>"
   [(set (match_operand:I48MODE 0 "memory_operand" "+m")
-	(unspec_volatile:I48MODE
+	(unspec:I48MODE
 	  [(FETCHOP:I48MODE (match_dup 0)
 	     (match_operand:I48MODE 1 "<fetchop_pred>" "<fetchop_constr>"))]
-	  UNSPECV_ATOMIC))
+	  UNSPEC_ATOMIC))
    (clobber (match_scratch:I48MODE 2 "=&r"))]
   ""
   "#"
@@ -93,10 +94,10 @@
 
 (define_insn_and_split "sync_nand<mode>"
   [(set (match_operand:I48MODE 0 "memory_operand" "+m")
-	(unspec_volatile:I48MODE
+	(unspec:I48MODE
 	  [(and:I48MODE (not:I48MODE (match_dup 0))
 	     (match_operand:I48MODE 1 "register_operand" "r"))]
-	  UNSPECV_ATOMIC))
+	  UNSPEC_ATOMIC))
    (clobber (match_scratch:I48MODE 2 "=&r"))]
   ""
   "#"
@@ -113,10 +114,10 @@
   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
 	(match_operand:I48MODE 1 "memory_operand" "+m"))
    (set (match_dup 1)
-	(unspec_volatile:I48MODE
+	(unspec:I48MODE
 	  [(FETCHOP:I48MODE (match_dup 1)
 	     (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>"))]
-	  UNSPECV_ATOMIC))
+	  UNSPEC_ATOMIC))
    (clobber (match_scratch:I48MODE 3 "=&r"))]
   ""
   "#"
@@ -133,10 +134,10 @@
   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
 	(match_operand:I48MODE 1 "memory_operand" "+m"))
    (set (match_dup 1)
-	(unspec_volatile:I48MODE
+	(unspec:I48MODE
 	  [(and:I48MODE (not:I48MODE (match_dup 1))
 	     (match_operand:I48MODE 2 "register_operand" "r"))]
-	  UNSPECV_ATOMIC))
+	  UNSPEC_ATOMIC))
    (clobber (match_scratch:I48MODE 3 "=&r"))]
   ""
   "#"
@@ -155,9 +156,9 @@
 	  (match_operand:I48MODE 1 "memory_operand" "+m")
 	  (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>")))
    (set (match_dup 1)
-	(unspec_volatile:I48MODE
+	(unspec:I48MODE
 	  [(FETCHOP:I48MODE (match_dup 1) (match_dup 2))]
-	  UNSPECV_ATOMIC))
+	  UNSPEC_ATOMIC))
    (clobber (match_scratch:I48MODE 3 "=&r"))]
   ""
   "#"
@@ -176,9 +177,9 @@
 	  (not:I48MODE (match_operand:I48MODE 1 "memory_operand" "+m"))
 	  (match_operand:I48MODE 2 "register_operand" "r")))
    (set (match_dup 1)
-	(unspec_volatile:I48MODE
+	(unspec:I48MODE
 	  [(and:I48MODE (not:I48MODE (match_dup 1)) (match_dup 2))]
-	  UNSPECV_ATOMIC))
+	  UNSPEC_ATOMIC))
    (clobber (match_scratch:I48MODE 3 "=&r"))]
   ""
   "#"
@@ -192,14 +193,50 @@
   [(set_attr "type" "multi")])
 
 (define_expand "sync_compare_and_swap<mode>"
+  [(match_operand:I12MODE 0 "register_operand" "")
+   (match_operand:I12MODE 1 "memory_operand" "")
+   (match_operand:I12MODE 2 "register_operand" "")
+   (match_operand:I12MODE 3 "add_operand" "")]
+  ""
+{
+  alpha_expand_compare_and_swap_12 (operands[0], operands[1],
+				    operands[2], operands[3]);
+  DONE;
+})
+
+(define_insn_and_split "sync_compare_and_swap<mode>_1"
+  [(set (match_operand:DI 0 "register_operand" "=&r,&r")
+	(zero_extend:DI
+	  (mem:I12MODE (match_operand:DI 1 "register_operand" "r,r"))))
+   (set (mem:I12MODE (match_dup 1))
+	(unspec:I12MODE
+	  [(match_operand:DI 2 "reg_or_8bit_operand" "J,rI")
+	   (match_operand:DI 3 "register_operand" "r,r")
+	   (match_operand:DI 4 "register_operand" "r,r")]
+	  UNSPEC_CMPXCHG))
+   (clobber (match_scratch:DI 5 "=&r,&r"))
+   (clobber (match_scratch:DI 6 "=X,&r"))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  alpha_split_compare_and_swap_12 (<MODE>mode, operands[0], operands[1],
+				   operands[2], operands[3], operands[4],
+				   operands[5], operands[6]);
+  DONE;
+}
+  [(set_attr "type" "multi")])
+
+(define_expand "sync_compare_and_swap<mode>"
   [(parallel
      [(set (match_operand:I48MODE 0 "register_operand" "")
 	   (match_operand:I48MODE 1 "memory_operand" ""))
       (set (match_dup 1)
-	   (unspec_volatile:I48MODE
+	   (unspec:I48MODE
 	     [(match_operand:I48MODE 2 "reg_or_8bit_operand" "")
 	      (match_operand:I48MODE 3 "add_operand" "rKL")]
-	     UNSPECV_CMPXCHG))
+	     UNSPEC_CMPXCHG))
       (clobber (match_scratch:I48MODE 4 "=&r"))])]
   ""
 {
@@ -211,10 +248,10 @@
   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
 	(match_operand:I48MODE 1 "memory_operand" "+m"))
    (set (match_dup 1)
-	(unspec_volatile:I48MODE
+	(unspec:I48MODE
 	  [(match_operand:DI 2 "reg_or_8bit_operand" "rI")
 	   (match_operand:I48MODE 3 "add_operand" "rKL")]
-	  UNSPECV_CMPXCHG))
+	  UNSPEC_CMPXCHG))
    (clobber (match_scratch:I48MODE 4 "=&r"))]
   ""
   "#"
@@ -227,13 +264,44 @@
 }
   [(set_attr "type" "multi")])
 
+(define_expand "sync_lock_test_and_set<mode>"
+  [(match_operand:I12MODE 0 "register_operand" "")
+   (match_operand:I12MODE 1 "memory_operand" "")
+   (match_operand:I12MODE 2 "register_operand" "")]
+  ""
+{
+  alpha_expand_lock_test_and_set_12 (operands[0], operands[1], operands[2]);
+  DONE;
+})
+
+(define_insn_and_split "sync_lock_test_and_set<mode>_1"
+  [(set (match_operand:DI 0 "register_operand" "=&r")
+	(zero_extend:DI
+	  (mem:I12MODE (match_operand:DI 1 "register_operand" "r"))))
+   (set (mem:I12MODE (match_dup 1))
+	(unspec:I12MODE
+	  [(match_operand:DI 2 "reg_or_8bit_operand" "rI")
+	   (match_operand:DI 3 "register_operand" "r")]
+	  UNSPEC_XCHG))
+   (clobber (match_scratch:DI 4 "=&r"))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  alpha_split_lock_test_and_set_12 (<MODE>mode, operands[0], operands[1],
+				    operands[2], operands[3], operands[4]);
+  DONE;
+}
+  [(set_attr "type" "multi")])
+
 (define_insn_and_split "sync_lock_test_and_set<mode>"
   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
 	(match_operand:I48MODE 1 "memory_operand" "+m"))
    (set (match_dup 1)
-	(unspec_volatile:I48MODE
+	(unspec:I48MODE
 	  [(match_operand:I48MODE 2 "add_operand" "rKL")]
-	  UNSPECV_XCHG))
+	  UNSPEC_XCHG))
    (clobber (match_scratch:I48MODE 3 "=&r"))]
   ""
   "#"
Index: gcc/testsuite/lib/target-supports.exp
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/lib/target-supports.exp,v
retrieving revision 1.67
diff -u -p -d -r1.67 target-supports.exp
--- gcc/testsuite/lib/target-supports.exp	29 Jun 2005 18:25:12 -0000	1.67
+++ gcc/testsuite/lib/target-supports.exp	9 Jul 2005 18:16:54 -0000
@@ -1122,6 +1122,7 @@ proc check_effective_target_sync_char_sh
         if { [istarget ia64-*-*]
 	     || [istarget i?86-*-*]
 	     || [istarget x86_64-*-*]
+	     || [istarget alpha*-*-*] 
 	     || [istarget powerpc*-*-*] } {
            set et_sync_char_short_saved 1
         }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]