1/* Out-of-line libgcc versions of __sync_* builtins. */ 2/* Copyright (C) 2008-2015 Free Software Foundation, Inc. 3 4This file is part of GCC. 5 6GCC is free software; you can redistribute it and/or modify it under 7the terms of the GNU General Public License as published by the Free 8Software Foundation; either version 3, or (at your option) any later 9version. 10 11GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12WARRANTY; without even the implied warranty of MERCHANTABILITY or 13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14for more details. 15 16Under Section 7 of GPL version 3, you are granted additional 17permissions described in the GCC Runtime Library Exception, version 183.1, as published by the Free Software Foundation. 19 20You should have received a copy of the GNU General Public License and 21a copy of the GCC Runtime Library Exception along with this program; 22see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23<http://www.gnu.org/licenses/>. */ 24 25/* This file is used by targets whose makefiles define SYNC 26 to "yes". It is compiled with SYNC_CFLAGS and provides 27 out-of-line versions of all relevant __sync_* primitives. 28 29 These routines are intended for targets like MIPS that have two 30 ISA encodings (the "normal" ISA and the MIPS16 ISA). The normal 31 ISA provides full synchronization capabilities but the MIPS16 ISA 32 has no encoding for them. MIPS16 code must therefore call external 33 non-MIPS16 implementations of the __sync_* routines. 34 35 The file is compiled once for each routine. The following __foo 36 routines are selected by defining a macro called L<foo>: 37 38 __sync_synchronize 39 40 The following __foo_N routines are selected by defining FN=foo 41 and SIZE=N: 42 43 __sync_fetch_and_add_N 44 __sync_fetch_and_sub_N 45 __sync_fetch_and_or_N 46 __sync_fetch_and_and_N 47 __sync_fetch_and_xor_N 48 __sync_fetch_and_nand_N 49 __sync_add_and_fetch_N 50 __sync_sub_and_fetch_N 51 __sync_or_and_fetch_N 52 __sync_and_and_fetch_N 53 __sync_xor_and_fetch_N 54 __sync_nand_and_fetch_N 55 __sync_bool_compare_and_swap_N 56 __sync_val_compare_and_swap_N 57 __sync_lock_test_and_set_N 58 59 SIZE can be 1, 2, 4, 8 or 16. __foo_N is omitted if the target does 60 not provide __sync_compare_and_swap_N. 61 62 Note that __sync_lock_release does not fall back on external 63 __sync_lock_release_N functions. The default implementation 64 of __sync_lock_release is a call to __sync_synchronize followed 65 by a store of zero, so we don't need separate library functions 66 for it. */ 67 68#if defined FN 69 70/* Define functions called __sync_<NAME>_<UNITS>, with one macro per 71 signature. TYPE is a type that has UNITS bytes. */ 72 73#define DEFINE_V_PV(NAME, UNITS, TYPE) \ 74 TYPE \ 75 __##NAME##_##UNITS (TYPE *ptr, TYPE value) \ 76 { \ 77 return __##NAME (ptr, value); \ 78 } 79 80#define DEFINE_V_PVV(NAME, UNITS, TYPE) \ 81 TYPE \ 82 __##NAME##_##UNITS (TYPE *ptr, TYPE value1, TYPE value2) \ 83 { \ 84 return __##NAME (ptr, value1, value2); \ 85 } 86 87#define DEFINE_BOOL_PVV(NAME, UNITS, TYPE) \ 88 _Bool \ 89 __##NAME##_##UNITS (TYPE *ptr, TYPE value1, TYPE value2) \ 90 { \ 91 return __##NAME (ptr, value1, value2); \ 92 } 93 94/* Map function names to the appropriate DEFINE_* macro. */ 95 96#define local_sync_fetch_and_add DEFINE_V_PV 97#define local_sync_fetch_and_sub DEFINE_V_PV 98#define local_sync_fetch_and_or DEFINE_V_PV 99#define local_sync_fetch_and_and DEFINE_V_PV 100#define local_sync_fetch_and_xor DEFINE_V_PV 101#define local_sync_fetch_and_nand DEFINE_V_PV 102 103#define local_sync_add_and_fetch DEFINE_V_PV 104#define local_sync_sub_and_fetch DEFINE_V_PV 105#define local_sync_or_and_fetch DEFINE_V_PV 106#define local_sync_and_and_fetch DEFINE_V_PV 107#define local_sync_xor_and_fetch DEFINE_V_PV 108#define local_sync_nand_and_fetch DEFINE_V_PV 109 110#define local_sync_bool_compare_and_swap DEFINE_BOOL_PVV 111#define local_sync_val_compare_and_swap DEFINE_V_PVV 112 113#define local_sync_lock_test_and_set DEFINE_V_PV 114 115/* Define the function __<NAME>_<UNITS>, given that TYPE is a type with 116 UNITS bytes. */ 117#define DEFINE1(NAME, UNITS, TYPE) \ 118 static int unused[sizeof (TYPE) == UNITS ? 1 : -1] \ 119 __attribute__((unused)); \ 120 local_##NAME (NAME, UNITS, TYPE); 121 122/* As above, but performing macro expansion on the arguments. */ 123#define DEFINE(NAME, UNITS, TYPE) DEFINE1 (NAME, UNITS, TYPE) 124 125/* Find an appropriate type TYPE for SIZE and invoke DEFINE (FN, SIZE, TYPE). 126 127 The types chosen here may be incorrect for some targets. 128 For example, targets with 16-byte atomicity support might not 129 support OImode. We would need some kind of target-specific 130 override if that becomes a problem. */ 131 132#if SIZE == 1 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 133 134typedef unsigned int UQItype __attribute__((mode (QI))); 135DEFINE (FN, 1, UQItype) 136 137#elif SIZE == 2 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 138 139typedef unsigned int UHItype __attribute__((mode (HI))); 140DEFINE (FN, 2, UHItype) 141 142#elif SIZE == 4 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 143 144typedef unsigned int USItype __attribute__((mode (SI))); 145DEFINE (FN, 4, USItype) 146 147#elif SIZE == 8 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 148 149typedef unsigned int UDItype __attribute__((mode (DI))); 150DEFINE (FN, 8, UDItype) 151 152#elif SIZE == 16 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 153 154typedef unsigned int UOItype __attribute__((mode (OI))); 155DEFINE (FN, 8, UOItype) 156 157#endif 158 159#elif __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 \ 160 || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 \ 161 || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 \ 162 || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 \ 163 || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 164 165#if defined Lsync_synchronize 166 167void 168__sync_synchronize (void) 169{ 170 __sync_synchronize (); 171} 172 173#endif 174 175#endif 176