OSDN Git Service

gcc/
authorbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 3 Sep 2009 15:37:28 +0000 (15:37 +0000)
committerbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 3 Sep 2009 15:37:28 +0000 (15:37 +0000)
* config/bfin/linux.h (TARGET_SUPPORTS_SYNC_CALLS): Define to 1.
* config/bfin/uclinux.h (TARGET_SUPPORTS_SYNC_CALLS): Define to 1.
* config/bfin/bfin.h (TARGET_SUPPORTS_SYNC_CALLS): Provide default of
0.
* config/bfin/sync.md: New file.
* config/bfin/bfin.md: Include it.
(UNSPEC_ATOMIC): New.
(UNSPEC_ONES): Provide a unique number.

From Jie Zhang <jie.zhang@analog.com>:
* config/bfin/bfin.c (ret_regs): New.
(must_save_fp_p): Don't return true because of frame_pointer_needed.
(must_save_rets_p): New.
(n_regs_saved_by_prologue): Use must_save_rets_p instead of
current_function_is_leaf.
(do_link): Likewise.
(do_unlink): Likewise.
(expand_interrupt_handler_prologue): Use ret_regs array.
(expand_interrupt_handler_epilogue): Use ret_regs array and
pass return register to gen_return_internal.
(bfin_expand_epilogue): Pass return register to
gen_return_internal.
(bfin_expand_call): Explicitly clobber RETS.
* config/bfin/bfin.h (FUNCTION_RETURN_REGISTERS): Define.
* config/bfin/bfin.md (call_symbol_fdpic, call_value_symbol_fdpic,
call_insn_fdpic, call_value_insn_fdpic, call_symbol,
call_value_symbol, call_insn, call_value_insn): Explicitly clobber
RETS.
(return_internal): Take a reg rtx rather than the register number.

gcc/testsuite/
* lib/target-supports.exp (check_effective_target_sync_int_long):
Supported on Blackfin Linux targets.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@151381 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/bfin/bfin.c
gcc/config/bfin/bfin.h
gcc/config/bfin/bfin.md
gcc/config/bfin/linux.h
gcc/config/bfin/sync.md [new file with mode: 0644]
gcc/config/bfin/uclinux.h
gcc/testsuite/ChangeLog
gcc/testsuite/lib/target-supports.exp

index 39323e5..ca35f9c 100644 (file)
@@ -1,3 +1,35 @@
+2009-09-03  Bernd Schmidt  <bernd.schmidt@analog.com>
+
+       * config/bfin/linux.h (TARGET_SUPPORTS_SYNC_CALLS): Define to 1.
+       * config/bfin/uclinux.h (TARGET_SUPPORTS_SYNC_CALLS): Define to 1.
+       * config/bfin/bfin.h (TARGET_SUPPORTS_SYNC_CALLS): Provide default of
+       0.
+       * config/bfin/sync.md: New file.
+       * config/bfin/bfin.md: Include it.
+       (UNSPEC_ATOMIC): New.
+       (UNSPEC_ONES): Provide a unique number.
+
+       From Jie Zhang <jie.zhang@analog.com>:
+       * config/bfin/bfin.c (ret_regs): New.
+       (must_save_fp_p): Don't return true because of frame_pointer_needed.
+       (must_save_rets_p): New.
+       (n_regs_saved_by_prologue): Use must_save_rets_p instead of
+       current_function_is_leaf.
+       (do_link): Likewise.
+       (do_unlink): Likewise.
+       (expand_interrupt_handler_prologue): Use ret_regs array.
+       (expand_interrupt_handler_epilogue): Use ret_regs array and
+       pass return register to gen_return_internal.
+       (bfin_expand_epilogue): Pass return register to
+       gen_return_internal.
+       (bfin_expand_call): Explicitly clobber RETS.
+       * config/bfin/bfin.h (FUNCTION_RETURN_REGISTERS): Define.
+       * config/bfin/bfin.md (call_symbol_fdpic, call_value_symbol_fdpic,
+       call_insn_fdpic, call_value_insn_fdpic, call_symbol,
+       call_value_symbol, call_insn, call_value_insn): Explicitly clobber
+       RETS.
+       (return_internal): Take a reg rtx rather than the register number.
+
 2009-09-03  H.J. Lu  <hongjiu.lu@intel.com>
 
        * tree-parloops.c (parallelize_loops): Cast to HOST_WIDE_INT
index 61da6db..ebcd825 100644 (file)
@@ -63,6 +63,7 @@ struct GTY(()) machine_function
   /* Set if we are notified by the doloop pass that a hardware loop
      was created.  */
   int has_hardware_loops;
+
   /* Set if we create a memcpy pattern that uses loop registers.  */
   int has_loopreg_clobber;
 };
@@ -81,6 +82,7 @@ const char *dregs_pair_names[] =  DREGS_PAIR_NAMES;
 const char *byte_reg_names[]   =  BYTE_REGISTER_NAMES;
 
 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
+static int ret_regs[] = FUNCTION_RETURN_REGISTERS;
 
 /* Nonzero if -mshared-library-id was given.  */
 static int bfin_lib_id_given;
@@ -532,7 +534,14 @@ n_pregs_to_save (bool is_inthandler, bool consecutive)
 static bool
 must_save_fp_p (void)
 {
-  return frame_pointer_needed || df_regs_ever_live_p (REG_FP);
+  return df_regs_ever_live_p (REG_FP);
+}
+
+/* Determine if we are going to save the RETS register.  */
+static bool
+must_save_rets_p (void)
+{
+  return df_regs_ever_live_p (REG_RETS);
 }
 
 static bool
@@ -844,13 +853,12 @@ n_regs_saved_by_prologue (void)
   int i;
 
   if (all || stack_frame_needed_p ())
-    /* We use a LINK instruction in this case.  */
     n += 2;
   else
     {
       if (must_save_fp_p ())
        n++;
-      if (! current_function_is_leaf)
+      if (must_save_rets_p ())
        n++;
     }
 
@@ -1092,12 +1100,13 @@ do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
 {
   frame_size += arg_area_size ();
 
-  if (all || stack_frame_needed_p ()
-      || (must_save_fp_p () && ! current_function_is_leaf))
+  if (all
+      || stack_frame_needed_p ()
+      || (must_save_rets_p () && must_save_fp_p ()))
     emit_link_insn (spreg, frame_size);
   else
     {
-      if (! current_function_is_leaf)
+      if (must_save_rets_p ())
        {
          rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
                                            gen_rtx_PRE_DEC (Pmode, spreg)),
@@ -1127,20 +1136,20 @@ do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p)
 {
   frame_size += arg_area_size ();
 
-  if (all || stack_frame_needed_p ())
+  if (stack_frame_needed_p ())
     emit_insn (gen_unlink ());
   else 
     {
       rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
 
       add_to_reg (spreg, frame_size, 0, epilogue_p);
-      if (must_save_fp_p ())
+      if (all || must_save_fp_p ())
        {
          rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
          emit_move_insn (fpreg, postinc);
          emit_use (fpreg);
        }
-      if (! current_function_is_leaf)
+      if (all || must_save_rets_p ())
        {
          emit_move_insn (bfin_rets_rtx, postinc);
          emit_use (bfin_rets_rtx);
@@ -1194,9 +1203,7 @@ expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind, bool all)
   
   if (lookup_attribute ("nesting", attrs))
     {
-      rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
-                                       : fkind == NMI_HANDLER ? REG_RETN
-                                       : REG_RETI));
+      rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
       insn = emit_move_insn (predec, srcreg);
       RTX_FRAME_RELATED_P (insn) = 1;
     }
@@ -1238,9 +1245,7 @@ expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind, bool all)
 
   if (lookup_attribute ("nesting", attrs))
     {
-      rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
-                                       : fkind == NMI_HANDLER ? REG_RETN
-                                       : REG_RETI));
+      rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
       emit_move_insn (srcreg, postinc);
     }
 
@@ -1256,7 +1261,7 @@ expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind, bool all)
   if (fkind == EXCPT_HANDLER)
     emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
 
-  emit_jump_insn (gen_return_internal (GEN_INT (fkind)));
+  emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, ret_regs[fkind])));
 }
 
 /* Used while emitting the prologue to generate code to load the correct value
@@ -1392,7 +1397,7 @@ bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p)
   if (eh_return)
     emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
 
-  emit_jump_insn (gen_return_internal (GEN_INT (SUBROUTINE)));
+  emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, REG_RETS)));
 }
 \f
 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG.  */
@@ -2193,9 +2198,10 @@ bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
 {
   rtx use = NULL, call;
   rtx callee = XEXP (fnaddr, 0);
-  int nelts = 2 + !!sibcall;
+  int nelts = 3;
   rtx pat;
   rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
+  rtx retsreg = gen_rtx_REG (Pmode, REG_RETS);
   int n;
 
   /* In an untyped call, we can get NULL for operand 2.  */
@@ -2272,6 +2278,8 @@ bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
   XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
   if (sibcall)
     XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
+  else
+    XVECEXP (pat, 0, n++) = gen_rtx_CLOBBER (VOIDmode, retsreg);
   call = emit_call_insn (pat);
   if (use)
     CALL_INSN_FUNCTION_USAGE (call) = use;
index a9ff6fa..53a7957 100644 (file)
@@ -794,6 +794,7 @@ enum reg_class
 typedef enum {
   SUBROUTINE, INTERRUPT_HANDLER, EXCPT_HANDLER, NMI_HANDLER
 } e_funkind;
+#define FUNCTION_RETURN_REGISTERS { REG_RETS, REG_RETI, REG_RETX, REG_RETN }
 
 #define FUNCTION_ARG_REGISTERS { REG_R0, REG_R1, REG_R2, -1 }
 
@@ -1258,4 +1259,8 @@ extern int splitting_for_sched, splitting_loops;
 
 #define PRINT_OPERAND_PUNCT_VALID_P(CHAR) ((CHAR) == '!')
 
+#ifndef TARGET_SUPPORTS_SYNC_CALLS
+#define TARGET_SUPPORTS_SYNC_CALLS 0
+#endif
+
 #endif /*  _BFIN_CONFIG */
index a363870..01e4012 100644 (file)
    ;; Distinguish a 32-bit version of an insn from a 16-bit version.
    (UNSPEC_32BIT 11)
    (UNSPEC_NOP 12)
-   (UNSPEC_ONES 12)])
+   (UNSPEC_ONES 13)
+   (UNSPEC_ATOMIC 14)])
 
 (define_constants
   [(UNSPEC_VOLATILE_CSYNC 1)
   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "Q"))
         (match_operand 1 "general_operand" "g"))
    (use (match_operand:SI 2 "register_operand" "Z"))
-   (use (match_operand 3 "" ""))]
+   (use (match_operand 3 "" ""))
+   (clobber (reg:SI REG_RETS))]
   "! SIBLING_CALL_P (insn)
    && GET_CODE (operands[0]) == SYMBOL_REF
    && !bfin_longcall_p (operands[0], INTVAL (operands[3]))"
         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "Q"))
              (match_operand 2 "general_operand" "g")))
    (use (match_operand:SI 3 "register_operand" "Z"))
-   (use (match_operand 4 "" ""))]
+   (use (match_operand 4 "" ""))
+   (clobber (reg:SI REG_RETS))]
   "! SIBLING_CALL_P (insn)
    && GET_CODE (operands[1]) == SYMBOL_REF
    && !bfin_longcall_p (operands[1], INTVAL (operands[4]))"
   [(call (mem:SI (match_operand:SI 0 "register_no_elim_operand" "Y"))
         (match_operand 1 "general_operand" "g"))
    (use (match_operand:SI 2 "register_operand" "Z"))
-   (use (match_operand 3 "" ""))]
+   (use (match_operand 3 "" ""))
+   (clobber (reg:SI REG_RETS))]
   "! SIBLING_CALL_P (insn)"
   "call (%0);"
   [(set_attr "type" "call")
         (call (mem:SI (match_operand:SI 1 "register_no_elim_operand" "Y"))
              (match_operand 2 "general_operand" "g")))
    (use (match_operand:SI 3 "register_operand" "Z"))
-   (use (match_operand 4 "" ""))]
+   (use (match_operand 4 "" ""))
+   (clobber (reg:SI REG_RETS))]
   "! SIBLING_CALL_P (insn)"
   "call (%1);"
   [(set_attr "type" "call")
 (define_insn "*call_symbol"
   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "Q"))
         (match_operand 1 "general_operand" "g"))
-   (use (match_operand 2 "" ""))]
+   (use (match_operand 2 "" ""))
+   (clobber (reg:SI REG_RETS))]
   "! SIBLING_CALL_P (insn)
    && (!TARGET_ID_SHARED_LIBRARY || TARGET_LEAF_ID_SHARED_LIBRARY)
    && GET_CODE (operands[0]) == SYMBOL_REF
   [(set (match_operand 0 "register_operand" "=d")
         (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "Q"))
              (match_operand 2 "general_operand" "g")))
-   (use (match_operand 3 "" ""))]
+   (use (match_operand 3 "" ""))
+   (clobber (reg:SI REG_RETS))]
   "! SIBLING_CALL_P (insn)
    && (!TARGET_ID_SHARED_LIBRARY || TARGET_LEAF_ID_SHARED_LIBRARY)
    && GET_CODE (operands[1]) == SYMBOL_REF
 (define_insn "*call_insn"
   [(call (mem:SI (match_operand:SI 0 "register_no_elim_operand" "a"))
         (match_operand 1 "general_operand" "g"))
-   (use (match_operand 2 "" ""))]
+   (use (match_operand 2 "" ""))
+   (clobber (reg:SI REG_RETS))]
   "! SIBLING_CALL_P (insn)"
   "call (%0);"
   [(set_attr "type" "call")
   [(set (match_operand 0 "register_operand" "=d")
         (call (mem:SI (match_operand:SI 1 "register_no_elim_operand" "a"))
              (match_operand 2 "general_operand" "g")))
-   (use (match_operand 3 "" ""))]
+   (use (match_operand 3 "" ""))
+   (clobber (reg:SI REG_RETS))]
   "! SIBLING_CALL_P (insn)"
   "call (%1);"
   [(set_attr "type" "call")
 
 (define_insn "return_internal"
   [(return)
-   (unspec [(match_operand 0 "immediate_operand" "i")] UNSPEC_RETURN)]
+   (use (match_operand 0 "register_operand" ""))]
   "reload_completed"
 {
-  switch (INTVAL (operands[0]))
+  switch (REGNO (operands[0]))
     {
-    case EXCPT_HANDLER:
+    case REG_RETX:
       return "rtx;";
-    case NMI_HANDLER:
+    case REG_RETN:
       return "rtn;";
-    case INTERRUPT_HANDLER:
+    case REG_RETI:
       return "rti;";
-    case SUBROUTINE:
+    case REG_RETS:
       return "rts;";
     }
   gcc_unreachable ();
   "DISALGNEXCPT || %0 = [%1];"
   [(set_attr "type" "mcld")
    (set_attr "length" "8")])
+
+(include "sync.md")
index 5d57680..5c716cd 100644 (file)
@@ -49,3 +49,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    %{static}} -init __init -fini __fini"
 
 #define MD_UNWIND_SUPPORT "config/bfin/linux-unwind.h"
+
+#undef TARGET_SUPPORTS_SYNC_CALLS
+#define TARGET_SUPPORTS_SYNC_CALLS 1
diff --git a/gcc/config/bfin/sync.md b/gcc/config/bfin/sync.md
new file mode 100644 (file)
index 0000000..7025af4
--- /dev/null
@@ -0,0 +1,178 @@
+;; GCC machine description for Blackfin synchronization instructions.
+;; Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+;; Contributed by Analog Devices.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_code_iterator FETCHOP [plus minus ior and xor])
+(define_code_attr fetchop_name
+  [(plus "add") (minus "sub") (ior "ior") (and "and") (xor "xor")])
+(define_code_attr fetchop_addr
+  [(plus "1072") (minus "1088") (ior "1104") (and "1120") (xor "1136")])
+
+(define_insn "sync_<fetchop_name>si_internal"
+  [(set (mem:SI (match_operand:SI 0 "register_operand" "qA"))
+       (unspec:SI
+         [(FETCHOP:SI (mem:SI (match_dup 0))
+            (match_operand:SI 1 "register_operand" "q0"))
+          (match_operand:SI 2 "register_no_elim_operand" "a")]
+         UNSPEC_ATOMIC))
+   (clobber (match_scratch:SI 3 "=q0"))
+   (clobber (match_scratch:SI 4 "=q1"))
+   (clobber (reg:SI REG_RETS))]
+  "TARGET_SUPPORTS_SYNC_CALLS"
+  "call (%2);"
+  [(set_attr "type" "call")])
+
+(define_expand "sync_<fetchop_name>si"
+  [(parallel
+    [(set (match_operand:SI 0 "memory_operand" "+m")
+         (unspec:SI
+          [(FETCHOP:SI (match_dup 0)
+                       (match_operand:SI 1 "register_operand" "q0"))
+           (match_dup 2)]
+          UNSPEC_ATOMIC))
+     (clobber (match_scratch:SI 3 ""))
+     (clobber (match_scratch:SI 4 ""))
+     (clobber (reg:SI REG_RETS))])]
+  "TARGET_SUPPORTS_SYNC_CALLS"
+{
+  if (!REG_P (XEXP (operands[0], 0)))
+    {
+      operands[0] = shallow_copy_rtx (operands[0]);
+      XEXP (operands[0], 0) = force_reg (Pmode, XEXP (operands[0], 0));
+    }
+  operands[2] = force_reg (Pmode, GEN_INT (<fetchop_addr>));
+})
+
+(define_insn "sync_old_<fetchop_name>si_internal"
+  [(set (match_operand:SI 0 "register_operand" "=q1")
+       (mem:SI (match_operand:SI 1 "register_operand" "qA")))
+   (set (mem:SI (match_dup 1))
+       (unspec:SI
+         [(FETCHOP:SI (mem:SI (match_dup 1))
+            (match_operand:SI 2 "register_operand" "q0"))
+          (match_operand:SI 3 "register_no_elim_operand" "a")]
+         UNSPEC_ATOMIC))
+   (clobber (match_scratch:SI 4 "=q0"))
+   (clobber (reg:SI REG_RETS))]
+  "TARGET_SUPPORTS_SYNC_CALLS"
+  "call (%3);"
+  [(set_attr "type" "call")])
+
+(define_expand "sync_old_<fetchop_name>si"
+  [(parallel
+    [(set (match_operand:SI 0 "register_operand" "")
+         (match_operand:SI 1 "memory_operand" ""))
+     (set (match_dup 1)
+         (unspec:SI
+          [(FETCHOP:SI (match_dup 1)
+                       (match_operand:SI 2 "register_operand" ""))
+           (match_dup 3)]
+          UNSPEC_ATOMIC))
+     (clobber (match_scratch:SI 4 ""))
+     (clobber (reg:SI REG_RETS))])]
+  "TARGET_SUPPORTS_SYNC_CALLS"
+{
+  if (!REG_P (XEXP (operands[1], 0)))
+    {
+      operands[1] = shallow_copy_rtx (operands[1]);
+      XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0));
+    }
+  operands[3] = force_reg (Pmode, GEN_INT (<fetchop_addr>));
+})
+
+(define_insn "sync_new_<fetchop_name>si_internal"
+  [(set (match_operand:SI 0 "register_operand" "=q0")
+       (unspec:SI
+         [(FETCHOP:SI
+           (mem:SI (match_operand:SI 1 "register_operand" "qA"))
+           (match_operand:SI 2 "register_operand" "q0"))
+          (match_operand:SI 3 "register_no_elim_operand" "a")]
+         UNSPEC_ATOMIC))
+   (set (mem:SI (match_dup 1))
+       (unspec:SI
+         [(FETCHOP:SI (mem:SI (match_dup 1)) (match_dup 2))
+          (match_dup 3)]
+         UNSPEC_ATOMIC))
+   (clobber (match_scratch:SI 4 "=q1"))
+   (clobber (reg:SI REG_RETS))]
+  "TARGET_SUPPORTS_SYNC_CALLS"
+  "call (%3);"
+  [(set_attr "type" "call")])
+
+(define_expand "sync_new_<fetchop_name>si"
+  [(parallel
+    [(set (match_operand:SI 0 "register_operand" "")
+         (unspec:SI
+          [(FETCHOP:SI (match_operand:SI 1 "memory_operand" "")
+                       (match_operand:SI 2 "register_operand" ""))
+           (match_dup 3)]
+          UNSPEC_ATOMIC))
+     (set (match_dup 1)
+         (unspec:SI
+          [(FETCHOP:SI (match_dup 1) (match_dup 2))
+           (match_dup 3)]
+          UNSPEC_ATOMIC))
+     (clobber (match_scratch:SI 4 ""))
+     (clobber (reg:SI REG_RETS))])]
+  "TARGET_SUPPORTS_SYNC_CALLS"
+{
+  if (!REG_P (XEXP (operands[1], 0)))
+    {
+      operands[1] = shallow_copy_rtx (operands[1]);
+      XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0));
+    }
+  operands[3] = force_reg (Pmode, GEN_INT (<fetchop_addr>));
+})
+
+(define_insn "sync_compare_and_swapsi_internal"
+  [(set (match_operand:SI 0 "register_operand" "=q0")
+       (mem:SI (match_operand:SI 1 "register_operand" "qA")))
+   (set (mem:SI (match_dup 1))
+       (unspec:SI
+         [(mem:SI (match_dup 1))
+          (match_operand:SI 2 "register_operand" "q1")
+          (match_operand:SI 3 "register_operand" "q2")
+          (match_operand:SI 4 "register_no_elim_operand" "a")]
+         UNSPEC_ATOMIC))
+   (clobber (reg:SI REG_RETS))]
+  "TARGET_SUPPORTS_SYNC_CALLS"
+  "call (%4);"
+  [(set_attr "type" "call")])
+
+(define_expand "sync_compare_and_swapsi"
+  [(parallel
+    [(set (match_operand:SI 0 "register_operand" "")
+         (match_operand:SI 1 "memory_operand" ""))
+     (set (match_dup 1)
+         (unspec:SI
+          [(match_dup 1)
+           (match_operand:SI 2 "register_operand" "")
+           (match_operand:SI 3 "register_operand" "")
+           (match_dup 4)]
+          UNSPEC_ATOMIC))
+     (clobber (reg:SI REG_RETS))])]
+  "TARGET_SUPPORTS_SYNC_CALLS"
+{
+  if (!REG_P (XEXP (operands[1], 0)))
+    {
+      operands[1] = shallow_copy_rtx (operands[1]);
+      XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0));
+    }
+  operands[4] = force_reg (Pmode, GEN_INT (0x420));
+})
index 80419da..6001b23 100644 (file)
@@ -36,3 +36,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  --wrap=mmap --wrap=munmap --wrap=alloca\
  %{fmudflapth: --wrap=pthread_create\
 }} %{fmudflap|fmudflapth: --wrap=main}"
+
+#undef TARGET_SUPPORTS_SYNC_CALLS
+#define TARGET_SUPPORTS_SYNC_CALLS 1
index 06e5050..1317b16 100644 (file)
@@ -1,3 +1,8 @@
+2009-09-03  Bernd Schmidt  <bernd.schmidt@analog.com>
+
+       * lib/target-supports.exp (check_effective_target_sync_int_long):
+       Supported on Blackfin Linux targets.
+
 2009-09-02  David Daney  <ddaney@caviumnetworks.com>
 
        * gcc.c-torture/compile/builtin_unreachable-1.c: New testcase.
index c826b86..9189938 100644 (file)
@@ -2670,6 +2670,7 @@ proc check_effective_target_sync_int_long { } {
             || [istarget i?86-*-*]
             || [istarget x86_64-*-*]
             || [istarget alpha*-*-*] 
+            || [istarget bfin*-*linux*]
             || [istarget s390*-*-*] 
             || [istarget powerpc*-*-*]
             || [istarget sparc64-*-*]