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