xref: /netbsd-src/external/gpl3/gcc/dist/libgcc/sync.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
148fb7bfaSmrg /* Out-of-line libgcc versions of __sync_* builtins.  */
2*b1e83836Smrg /* Copyright (C) 2008-2022 Free Software Foundation, Inc.
348fb7bfaSmrg 
448fb7bfaSmrg This file is part of GCC.
548fb7bfaSmrg 
648fb7bfaSmrg GCC is free software; you can redistribute it and/or modify it under
748fb7bfaSmrg the terms of the GNU General Public License as published by the Free
848fb7bfaSmrg Software Foundation; either version 3, or (at your option) any later
948fb7bfaSmrg version.
1048fb7bfaSmrg 
1148fb7bfaSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1248fb7bfaSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
1348fb7bfaSmrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1448fb7bfaSmrg for more details.
1548fb7bfaSmrg 
1648fb7bfaSmrg Under Section 7 of GPL version 3, you are granted additional
1748fb7bfaSmrg permissions described in the GCC Runtime Library Exception, version
1848fb7bfaSmrg 3.1, as published by the Free Software Foundation.
1948fb7bfaSmrg 
2048fb7bfaSmrg You should have received a copy of the GNU General Public License and
2148fb7bfaSmrg a copy of the GCC Runtime Library Exception along with this program;
2248fb7bfaSmrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2348fb7bfaSmrg <http://www.gnu.org/licenses/>.  */
2448fb7bfaSmrg 
2548fb7bfaSmrg /* This file is used by targets whose makefiles define SYNC
2648fb7bfaSmrg    to "yes".  It is compiled with SYNC_CFLAGS and provides
2748fb7bfaSmrg    out-of-line versions of all relevant __sync_* primitives.
2848fb7bfaSmrg 
2948fb7bfaSmrg    These routines are intended for targets like MIPS that have two
3048fb7bfaSmrg    ISA encodings (the "normal" ISA and the MIPS16 ISA).  The normal
3148fb7bfaSmrg    ISA provides full synchronization capabilities but the MIPS16 ISA
3248fb7bfaSmrg    has no encoding for them.  MIPS16 code must therefore call external
3348fb7bfaSmrg    non-MIPS16 implementations of the __sync_* routines.
3448fb7bfaSmrg 
3548fb7bfaSmrg    The file is compiled once for each routine.  The following __foo
3648fb7bfaSmrg    routines are selected by defining a macro called L<foo>:
3748fb7bfaSmrg 
3848fb7bfaSmrg        __sync_synchronize
3948fb7bfaSmrg 
4048fb7bfaSmrg    The following __foo_N routines are selected by defining FN=foo
4148fb7bfaSmrg    and SIZE=N:
4248fb7bfaSmrg 
4348fb7bfaSmrg        __sync_fetch_and_add_N
4448fb7bfaSmrg        __sync_fetch_and_sub_N
4548fb7bfaSmrg        __sync_fetch_and_or_N
4648fb7bfaSmrg        __sync_fetch_and_and_N
4748fb7bfaSmrg        __sync_fetch_and_xor_N
4848fb7bfaSmrg        __sync_fetch_and_nand_N
4948fb7bfaSmrg        __sync_add_and_fetch_N
5048fb7bfaSmrg        __sync_sub_and_fetch_N
5148fb7bfaSmrg        __sync_or_and_fetch_N
5248fb7bfaSmrg        __sync_and_and_fetch_N
5348fb7bfaSmrg        __sync_xor_and_fetch_N
5448fb7bfaSmrg        __sync_nand_and_fetch_N
5548fb7bfaSmrg        __sync_bool_compare_and_swap_N
5648fb7bfaSmrg        __sync_val_compare_and_swap_N
5748fb7bfaSmrg        __sync_lock_test_and_set_N
5848fb7bfaSmrg 
5948fb7bfaSmrg    SIZE can be 1, 2, 4, 8 or 16.  __foo_N is omitted if the target does
6048fb7bfaSmrg    not provide __sync_compare_and_swap_N.
6148fb7bfaSmrg 
6248fb7bfaSmrg    Note that __sync_lock_release does not fall back on external
6348fb7bfaSmrg    __sync_lock_release_N functions.  The default implementation
6448fb7bfaSmrg    of __sync_lock_release is a call to __sync_synchronize followed
6548fb7bfaSmrg    by a store of zero, so we don't need separate library functions
6648fb7bfaSmrg    for it.  */
6748fb7bfaSmrg 
6848fb7bfaSmrg #if defined FN
6948fb7bfaSmrg 
704d5abbe8Smrg /* Define functions called __sync_<NAME>_<UNITS>, with one macro per
714d5abbe8Smrg    signature.  TYPE is a type that has UNITS bytes.  */
7248fb7bfaSmrg 
7348fb7bfaSmrg #define DEFINE_V_PV(NAME, UNITS, TYPE)					\
744d5abbe8Smrg   TYPE									\
754d5abbe8Smrg   __##NAME##_##UNITS (TYPE *ptr, TYPE value)				\
7648fb7bfaSmrg   {									\
7748fb7bfaSmrg     return __##NAME (ptr, value);					\
7848fb7bfaSmrg   }
7948fb7bfaSmrg 
8048fb7bfaSmrg #define DEFINE_V_PVV(NAME, UNITS, TYPE)					\
814d5abbe8Smrg   TYPE									\
824d5abbe8Smrg   __##NAME##_##UNITS (TYPE *ptr, TYPE value1, TYPE value2)		\
8348fb7bfaSmrg   {									\
8448fb7bfaSmrg     return __##NAME (ptr, value1, value2);				\
8548fb7bfaSmrg   }
8648fb7bfaSmrg 
8748fb7bfaSmrg #define DEFINE_BOOL_PVV(NAME, UNITS, TYPE)				\
884d5abbe8Smrg   _Bool									\
894d5abbe8Smrg   __##NAME##_##UNITS (TYPE *ptr, TYPE value1, TYPE value2)		\
9048fb7bfaSmrg   {									\
9148fb7bfaSmrg     return __##NAME (ptr, value1, value2);				\
9248fb7bfaSmrg   }
9348fb7bfaSmrg 
9448fb7bfaSmrg /* Map function names to the appropriate DEFINE_* macro.  */
9548fb7bfaSmrg 
9648fb7bfaSmrg #define local_sync_fetch_and_add DEFINE_V_PV
9748fb7bfaSmrg #define local_sync_fetch_and_sub DEFINE_V_PV
9848fb7bfaSmrg #define local_sync_fetch_and_or DEFINE_V_PV
9948fb7bfaSmrg #define local_sync_fetch_and_and DEFINE_V_PV
10048fb7bfaSmrg #define local_sync_fetch_and_xor DEFINE_V_PV
10148fb7bfaSmrg #define local_sync_fetch_and_nand DEFINE_V_PV
10248fb7bfaSmrg 
10348fb7bfaSmrg #define local_sync_add_and_fetch DEFINE_V_PV
10448fb7bfaSmrg #define local_sync_sub_and_fetch DEFINE_V_PV
10548fb7bfaSmrg #define local_sync_or_and_fetch DEFINE_V_PV
10648fb7bfaSmrg #define local_sync_and_and_fetch DEFINE_V_PV
10748fb7bfaSmrg #define local_sync_xor_and_fetch DEFINE_V_PV
10848fb7bfaSmrg #define local_sync_nand_and_fetch DEFINE_V_PV
10948fb7bfaSmrg 
11048fb7bfaSmrg #define local_sync_bool_compare_and_swap DEFINE_BOOL_PVV
11148fb7bfaSmrg #define local_sync_val_compare_and_swap DEFINE_V_PVV
11248fb7bfaSmrg 
11348fb7bfaSmrg #define local_sync_lock_test_and_set DEFINE_V_PV
11448fb7bfaSmrg 
11548fb7bfaSmrg /* Define the function __<NAME>_<UNITS>, given that TYPE is a type with
11648fb7bfaSmrg    UNITS bytes.  */
11748fb7bfaSmrg #define DEFINE1(NAME, UNITS, TYPE) \
11848fb7bfaSmrg   static int unused[sizeof (TYPE) == UNITS ? 1 : -1]	\
11948fb7bfaSmrg     __attribute__((unused));				\
1204d5abbe8Smrg   local_##NAME (NAME, UNITS, TYPE);
12148fb7bfaSmrg 
12248fb7bfaSmrg /* As above, but performing macro expansion on the arguments.  */
12348fb7bfaSmrg #define DEFINE(NAME, UNITS, TYPE) DEFINE1 (NAME, UNITS, TYPE)
12448fb7bfaSmrg 
12548fb7bfaSmrg /* Find an appropriate type TYPE for SIZE and invoke DEFINE (FN, SIZE, TYPE).
12648fb7bfaSmrg 
12748fb7bfaSmrg    The types chosen here may be incorrect for some targets.
12848fb7bfaSmrg    For example, targets with 16-byte atomicity support might not
12948fb7bfaSmrg    support OImode.  We would need some kind of target-specific
13048fb7bfaSmrg    override if that becomes a problem.  */
13148fb7bfaSmrg 
13248fb7bfaSmrg #if SIZE == 1 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
13348fb7bfaSmrg 
13448fb7bfaSmrg typedef unsigned int UQItype __attribute__((mode (QI)));
13548fb7bfaSmrg DEFINE (FN, 1, UQItype)
13648fb7bfaSmrg 
13748fb7bfaSmrg #elif SIZE == 2 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
13848fb7bfaSmrg 
13948fb7bfaSmrg typedef unsigned int UHItype __attribute__((mode (HI)));
14048fb7bfaSmrg DEFINE (FN, 2, UHItype)
14148fb7bfaSmrg 
14248fb7bfaSmrg #elif SIZE == 4 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
14348fb7bfaSmrg 
14448fb7bfaSmrg typedef unsigned int USItype __attribute__((mode (SI)));
14548fb7bfaSmrg DEFINE (FN, 4, USItype)
14648fb7bfaSmrg 
14748fb7bfaSmrg #elif SIZE == 8 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
14848fb7bfaSmrg 
14948fb7bfaSmrg typedef unsigned int UDItype __attribute__((mode (DI)));
15048fb7bfaSmrg DEFINE (FN, 8, UDItype)
15148fb7bfaSmrg 
15248fb7bfaSmrg #elif SIZE == 16 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
15348fb7bfaSmrg 
15448fb7bfaSmrg typedef unsigned int UOItype __attribute__((mode (OI)));
15548fb7bfaSmrg DEFINE (FN, 8, UOItype)
15648fb7bfaSmrg 
15748fb7bfaSmrg #endif
15848fb7bfaSmrg 
15948fb7bfaSmrg #elif __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 \
16048fb7bfaSmrg       || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 \
16148fb7bfaSmrg       || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 \
16248fb7bfaSmrg       || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 \
16348fb7bfaSmrg       || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
16448fb7bfaSmrg 
16548fb7bfaSmrg #if defined Lsync_synchronize
16648fb7bfaSmrg 
1674d5abbe8Smrg void
1684d5abbe8Smrg __sync_synchronize (void)
16948fb7bfaSmrg {
17048fb7bfaSmrg   __sync_synchronize ();
17148fb7bfaSmrg }
17248fb7bfaSmrg 
17348fb7bfaSmrg #endif
17448fb7bfaSmrg 
17548fb7bfaSmrg #endif
176