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