Add an atomic test and set pattern on tilegx.
authorWalter Lee <walt@tilera.com>
Thu, 21 Mar 2013 02:08:26 +0000 (02:08 +0000)
committerWalter Lee <walt@gcc.gnu.org>
Thu, 21 Mar 2013 02:08:26 +0000 (02:08 +0000)
      * config/tilegx/sync.md (atomic_test_and_set): New pattern.

From-SVN: r196848

gcc/ChangeLog
gcc/config/tilegx/sync.md

index 2cd7169932aab5f4906225f5968f0bc4976ed81b..5ecdc8ffc498c0e00e779df4fc54d299816a8212 100644 (file)
@@ -1,3 +1,7 @@
+2013-03-20  Walter Lee  <walt@tilera.com>
+
+       * config/tilegx/sync.md (atomic_test_and_set): New pattern.
+
 2013-03-20  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.md (*movoi_internal_avx): Emit insn template
index a853996162a2d1a2d1e793f228bb60fb75ddbd96..a4bea6b68895852e99ac28c9328dd3b986b4e281 100644 (file)
   tilegx_post_atomic_barrier (model);
   DONE;
 })
+
+
+(define_expand "atomic_test_and_set"
+  [(match_operand:QI 0 "register_operand" "")           ;; bool output
+   (match_operand:QI 1 "nonautoincmem_operand" "+U")    ;; memory
+   (match_operand:SI 2 "const_int_operand" "")]         ;; model
+  ""
+{
+  rtx addr, aligned_addr, aligned_mem, offset, word, shmt;
+  rtx tmp0, tmp1;
+  rtx result = operands[0];
+  rtx mem = operands[1];
+  enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+
+  addr = force_reg (Pmode, XEXP (mem, 0));
+
+  aligned_addr = gen_reg_rtx (Pmode);
+  emit_move_insn (aligned_addr, gen_rtx_AND (Pmode, addr, GEN_INT (-8)));
+
+  aligned_mem = change_address (mem, DImode, aligned_addr);
+  set_mem_alias_set (aligned_mem, 0);
+
+  offset = gen_reg_rtx (DImode);
+  emit_move_insn (offset, gen_rtx_AND (DImode, gen_lowpart (DImode, addr),
+                                       GEN_INT (7)));
+
+  tmp0 = gen_reg_rtx (DImode);
+  emit_move_insn (tmp0, GEN_INT (1));
+
+  shmt = gen_reg_rtx (DImode);
+  emit_move_insn (shmt, gen_rtx_ASHIFT (DImode, offset, GEN_INT (3)));
+
+  word = gen_reg_rtx (DImode);
+  emit_move_insn (word, gen_rtx_ASHIFT (DImode, tmp0,
+                                        gen_lowpart (SImode, shmt)));
+
+  tmp1 = gen_reg_rtx (DImode);
+  tilegx_pre_atomic_barrier (model);
+  emit_insn (gen_atomic_fetch_or_baredi (tmp1, aligned_mem, word));
+  tilegx_post_atomic_barrier (model);
+
+  emit_move_insn (gen_lowpart (DImode, result),
+                  gen_rtx_LSHIFTRT (DImode, tmp1,
+                                    gen_lowpart (SImode, shmt)));
+  DONE;
+})