xref: /netbsd-src/external/gpl3/gcc.old/dist/libgcc/sync.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* Out-of-line libgcc versions of __sync_* builtins.  */
2*8feb0f0bSmrg /* Copyright (C) 2008-2020 Free Software Foundation, Inc.
31debfc3dSmrg 
41debfc3dSmrg This file is part of GCC.
51debfc3dSmrg 
61debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
71debfc3dSmrg the terms of the GNU General Public License as published by the Free
81debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
91debfc3dSmrg version.
101debfc3dSmrg 
111debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
121debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
131debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
141debfc3dSmrg for more details.
151debfc3dSmrg 
161debfc3dSmrg Under Section 7 of GPL version 3, you are granted additional
171debfc3dSmrg permissions described in the GCC Runtime Library Exception, version
181debfc3dSmrg 3.1, as published by the Free Software Foundation.
191debfc3dSmrg 
201debfc3dSmrg You should have received a copy of the GNU General Public License and
211debfc3dSmrg a copy of the GCC Runtime Library Exception along with this program;
221debfc3dSmrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
231debfc3dSmrg <http://www.gnu.org/licenses/>.  */
241debfc3dSmrg 
251debfc3dSmrg /* This file is used by targets whose makefiles define SYNC
261debfc3dSmrg    to "yes".  It is compiled with SYNC_CFLAGS and provides
271debfc3dSmrg    out-of-line versions of all relevant __sync_* primitives.
281debfc3dSmrg 
291debfc3dSmrg    These routines are intended for targets like MIPS that have two
301debfc3dSmrg    ISA encodings (the "normal" ISA and the MIPS16 ISA).  The normal
311debfc3dSmrg    ISA provides full synchronization capabilities but the MIPS16 ISA
321debfc3dSmrg    has no encoding for them.  MIPS16 code must therefore call external
331debfc3dSmrg    non-MIPS16 implementations of the __sync_* routines.
341debfc3dSmrg 
351debfc3dSmrg    The file is compiled once for each routine.  The following __foo
361debfc3dSmrg    routines are selected by defining a macro called L<foo>:
371debfc3dSmrg 
381debfc3dSmrg        __sync_synchronize
391debfc3dSmrg 
401debfc3dSmrg    The following __foo_N routines are selected by defining FN=foo
411debfc3dSmrg    and SIZE=N:
421debfc3dSmrg 
431debfc3dSmrg        __sync_fetch_and_add_N
441debfc3dSmrg        __sync_fetch_and_sub_N
451debfc3dSmrg        __sync_fetch_and_or_N
461debfc3dSmrg        __sync_fetch_and_and_N
471debfc3dSmrg        __sync_fetch_and_xor_N
481debfc3dSmrg        __sync_fetch_and_nand_N
491debfc3dSmrg        __sync_add_and_fetch_N
501debfc3dSmrg        __sync_sub_and_fetch_N
511debfc3dSmrg        __sync_or_and_fetch_N
521debfc3dSmrg        __sync_and_and_fetch_N
531debfc3dSmrg        __sync_xor_and_fetch_N
541debfc3dSmrg        __sync_nand_and_fetch_N
551debfc3dSmrg        __sync_bool_compare_and_swap_N
561debfc3dSmrg        __sync_val_compare_and_swap_N
571debfc3dSmrg        __sync_lock_test_and_set_N
581debfc3dSmrg 
591debfc3dSmrg    SIZE can be 1, 2, 4, 8 or 16.  __foo_N is omitted if the target does
601debfc3dSmrg    not provide __sync_compare_and_swap_N.
611debfc3dSmrg 
621debfc3dSmrg    Note that __sync_lock_release does not fall back on external
631debfc3dSmrg    __sync_lock_release_N functions.  The default implementation
641debfc3dSmrg    of __sync_lock_release is a call to __sync_synchronize followed
651debfc3dSmrg    by a store of zero, so we don't need separate library functions
661debfc3dSmrg    for it.  */
671debfc3dSmrg 
681debfc3dSmrg #if defined FN
691debfc3dSmrg 
701debfc3dSmrg /* Define functions called __sync_<NAME>_<UNITS>, with one macro per
711debfc3dSmrg    signature.  TYPE is a type that has UNITS bytes.  */
721debfc3dSmrg 
731debfc3dSmrg #define DEFINE_V_PV(NAME, UNITS, TYPE)					\
741debfc3dSmrg   TYPE									\
751debfc3dSmrg   __##NAME##_##UNITS (TYPE *ptr, TYPE value)				\
761debfc3dSmrg   {									\
771debfc3dSmrg     return __##NAME (ptr, value);					\
781debfc3dSmrg   }
791debfc3dSmrg 
801debfc3dSmrg #define DEFINE_V_PVV(NAME, UNITS, TYPE)					\
811debfc3dSmrg   TYPE									\
821debfc3dSmrg   __##NAME##_##UNITS (TYPE *ptr, TYPE value1, TYPE value2)		\
831debfc3dSmrg   {									\
841debfc3dSmrg     return __##NAME (ptr, value1, value2);				\
851debfc3dSmrg   }
861debfc3dSmrg 
871debfc3dSmrg #define DEFINE_BOOL_PVV(NAME, UNITS, TYPE)				\
881debfc3dSmrg   _Bool									\
891debfc3dSmrg   __##NAME##_##UNITS (TYPE *ptr, TYPE value1, TYPE value2)		\
901debfc3dSmrg   {									\
911debfc3dSmrg     return __##NAME (ptr, value1, value2);				\
921debfc3dSmrg   }
931debfc3dSmrg 
941debfc3dSmrg /* Map function names to the appropriate DEFINE_* macro.  */
951debfc3dSmrg 
961debfc3dSmrg #define local_sync_fetch_and_add DEFINE_V_PV
971debfc3dSmrg #define local_sync_fetch_and_sub DEFINE_V_PV
981debfc3dSmrg #define local_sync_fetch_and_or DEFINE_V_PV
991debfc3dSmrg #define local_sync_fetch_and_and DEFINE_V_PV
1001debfc3dSmrg #define local_sync_fetch_and_xor DEFINE_V_PV
1011debfc3dSmrg #define local_sync_fetch_and_nand DEFINE_V_PV
1021debfc3dSmrg 
1031debfc3dSmrg #define local_sync_add_and_fetch DEFINE_V_PV
1041debfc3dSmrg #define local_sync_sub_and_fetch DEFINE_V_PV
1051debfc3dSmrg #define local_sync_or_and_fetch DEFINE_V_PV
1061debfc3dSmrg #define local_sync_and_and_fetch DEFINE_V_PV
1071debfc3dSmrg #define local_sync_xor_and_fetch DEFINE_V_PV
1081debfc3dSmrg #define local_sync_nand_and_fetch DEFINE_V_PV
1091debfc3dSmrg 
1101debfc3dSmrg #define local_sync_bool_compare_and_swap DEFINE_BOOL_PVV
1111debfc3dSmrg #define local_sync_val_compare_and_swap DEFINE_V_PVV
1121debfc3dSmrg 
1131debfc3dSmrg #define local_sync_lock_test_and_set DEFINE_V_PV
1141debfc3dSmrg 
1151debfc3dSmrg /* Define the function __<NAME>_<UNITS>, given that TYPE is a type with
1161debfc3dSmrg    UNITS bytes.  */
1171debfc3dSmrg #define DEFINE1(NAME, UNITS, TYPE) \
1181debfc3dSmrg   static int unused[sizeof (TYPE) == UNITS ? 1 : -1]	\
1191debfc3dSmrg     __attribute__((unused));				\
1201debfc3dSmrg   local_##NAME (NAME, UNITS, TYPE);
1211debfc3dSmrg 
1221debfc3dSmrg /* As above, but performing macro expansion on the arguments.  */
1231debfc3dSmrg #define DEFINE(NAME, UNITS, TYPE) DEFINE1 (NAME, UNITS, TYPE)
1241debfc3dSmrg 
1251debfc3dSmrg /* Find an appropriate type TYPE for SIZE and invoke DEFINE (FN, SIZE, TYPE).
1261debfc3dSmrg 
1271debfc3dSmrg    The types chosen here may be incorrect for some targets.
1281debfc3dSmrg    For example, targets with 16-byte atomicity support might not
1291debfc3dSmrg    support OImode.  We would need some kind of target-specific
1301debfc3dSmrg    override if that becomes a problem.  */
1311debfc3dSmrg 
1321debfc3dSmrg #if SIZE == 1 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
1331debfc3dSmrg 
1341debfc3dSmrg typedef unsigned int UQItype __attribute__((mode (QI)));
1351debfc3dSmrg DEFINE (FN, 1, UQItype)
1361debfc3dSmrg 
1371debfc3dSmrg #elif SIZE == 2 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
1381debfc3dSmrg 
1391debfc3dSmrg typedef unsigned int UHItype __attribute__((mode (HI)));
1401debfc3dSmrg DEFINE (FN, 2, UHItype)
1411debfc3dSmrg 
1421debfc3dSmrg #elif SIZE == 4 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
1431debfc3dSmrg 
1441debfc3dSmrg typedef unsigned int USItype __attribute__((mode (SI)));
1451debfc3dSmrg DEFINE (FN, 4, USItype)
1461debfc3dSmrg 
1471debfc3dSmrg #elif SIZE == 8 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
1481debfc3dSmrg 
1491debfc3dSmrg typedef unsigned int UDItype __attribute__((mode (DI)));
1501debfc3dSmrg DEFINE (FN, 8, UDItype)
1511debfc3dSmrg 
1521debfc3dSmrg #elif SIZE == 16 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
1531debfc3dSmrg 
1541debfc3dSmrg typedef unsigned int UOItype __attribute__((mode (OI)));
1551debfc3dSmrg DEFINE (FN, 8, UOItype)
1561debfc3dSmrg 
1571debfc3dSmrg #endif
1581debfc3dSmrg 
1591debfc3dSmrg #elif __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 \
1601debfc3dSmrg       || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 \
1611debfc3dSmrg       || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 \
1621debfc3dSmrg       || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 \
1631debfc3dSmrg       || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
1641debfc3dSmrg 
1651debfc3dSmrg #if defined Lsync_synchronize
1661debfc3dSmrg 
1671debfc3dSmrg void
1681debfc3dSmrg __sync_synchronize (void)
1691debfc3dSmrg {
1701debfc3dSmrg   __sync_synchronize ();
1711debfc3dSmrg }
1721debfc3dSmrg 
1731debfc3dSmrg #endif
1741debfc3dSmrg 
1751debfc3dSmrg #endif
176