1 /* Copyright (C) 2003-2014 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Andreas Schwab <schwab@suse.de>, 2003.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library. If not, see
17 <http://www.gnu.org/licenses/>. */
22 typedef int8_t atomic8_t;
23 typedef uint8_t uatomic8_t;
24 typedef int_fast8_t atomic_fast8_t;
25 typedef uint_fast8_t uatomic_fast8_t;
27 typedef int16_t atomic16_t;
28 typedef uint16_t uatomic16_t;
29 typedef int_fast16_t atomic_fast16_t;
30 typedef uint_fast16_t uatomic_fast16_t;
32 typedef int32_t atomic32_t;
33 typedef uint32_t uatomic32_t;
34 typedef int_fast32_t atomic_fast32_t;
35 typedef uint_fast32_t uatomic_fast32_t;
37 typedef int64_t atomic64_t;
38 typedef uint64_t uatomic64_t;
39 typedef int_fast64_t atomic_fast64_t;
40 typedef uint_fast64_t uatomic_fast64_t;
42 typedef intptr_t atomicptr_t;
43 typedef uintptr_t uatomicptr_t;
44 typedef intmax_t atomic_max_t;
45 typedef uintmax_t uatomic_max_t;
47 #define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
48 ({ __typeof (*(mem)) __ret; \
49 __asm __volatile ("cas%.b %0,%2,%1" \
50 : "=d" (__ret), "+m" (*(mem)) \
51 : "d" (newval), "0" (oldval)); \
54 #define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
55 ({ __typeof (*(mem)) __ret; \
56 __asm __volatile ("cas%.w %0,%2,%1" \
57 : "=d" (__ret), "+m" (*(mem)) \
58 : "d" (newval), "0" (oldval)); \
61 #define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
62 ({ __typeof (*(mem)) __ret; \
63 __asm __volatile ("cas%.l %0,%2,%1" \
64 : "=d" (__ret), "+m" (*(mem)) \
65 : "d" (newval), "0" (oldval)); \
68 # define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
69 ({ __typeof (*(mem)) __ret; \
70 __typeof (mem) __memp = (mem); \
71 __asm __volatile ("cas2%.l %0:%R0,%1:%R1,(%2):(%3)" \
73 : "d" (newval), "r" (__memp), \
74 "r" ((char *) __memp + 4), "0" (oldval) \
78 #define atomic_exchange_acq(mem, newvalue) \
79 ({ __typeof (*(mem)) __result = *(mem); \
80 if (sizeof (*(mem)) == 1) \
81 __asm __volatile ("1: cas%.b %0,%2,%1;" \
83 : "=d" (__result), "+m" (*(mem)) \
84 : "d" (newvalue), "0" (__result)); \
85 else if (sizeof (*(mem)) == 2) \
86 __asm __volatile ("1: cas%.w %0,%2,%1;" \
88 : "=d" (__result), "+m" (*(mem)) \
89 : "d" (newvalue), "0" (__result)); \
90 else if (sizeof (*(mem)) == 4) \
91 __asm __volatile ("1: cas%.l %0,%2,%1;" \
93 : "=d" (__result), "+m" (*(mem)) \
94 : "d" (newvalue), "0" (__result)); \
97 __typeof (mem) __memp = (mem); \
98 __asm __volatile ("1: cas2%.l %0:%R0,%1:%R1,(%2):(%3);" \
101 : "d" (newvalue), "r" (__memp), \
102 "r" ((char *) __memp + 4), "0" (__result) \
107 #define atomic_exchange_and_add(mem, value) \
108 ({ __typeof (*(mem)) __result = *(mem); \
109 __typeof (*(mem)) __temp; \
110 if (sizeof (*(mem)) == 1) \
111 __asm __volatile ("1: move%.b %0,%2;" \
113 " cas%.b %0,%2,%1;" \
115 : "=d" (__result), "+m" (*(mem)), \
117 : "d" (value), "0" (__result)); \
118 else if (sizeof (*(mem)) == 2) \
119 __asm __volatile ("1: move%.w %0,%2;" \
121 " cas%.w %0,%2,%1;" \
123 : "=d" (__result), "+m" (*(mem)), \
125 : "d" (value), "0" (__result)); \
126 else if (sizeof (*(mem)) == 4) \
127 __asm __volatile ("1: move%.l %0,%2;" \
129 " cas%.l %0,%2,%1;" \
131 : "=d" (__result), "+m" (*(mem)), \
133 : "d" (value), "0" (__result)); \
136 __typeof (mem) __memp = (mem); \
137 __asm __volatile ("1: move%.l %0,%1;" \
138 " move%.l %R0,%R1;" \
140 " addx%.l %R2,%R1;" \
141 " cas2%.l %0:%R0,%1:%R1,(%3):(%4);" \
143 : "=d" (__result), "=&d" (__temp) \
144 : "d" (value), "r" (__memp), \
145 "r" ((char *) __memp + 4), "0" (__result) \
150 #define atomic_add(mem, value) \
151 (void) ({ if (sizeof (*(mem)) == 1) \
152 __asm __volatile ("add%.b %1,%0" \
155 else if (sizeof (*(mem)) == 2) \
156 __asm __volatile ("add%.w %1,%0" \
159 else if (sizeof (*(mem)) == 4) \
160 __asm __volatile ("add%.l %1,%0" \
165 __typeof (mem) __memp = (mem); \
166 __typeof (*(mem)) __oldval = *__memp; \
167 __typeof (*(mem)) __temp; \
168 __asm __volatile ("1: move%.l %0,%1;" \
169 " move%.l %R0,%R1;" \
171 " addx%.l %R2,%R1;" \
172 " cas2%.l %0:%R0,%1:%R1,(%3):(%4);" \
174 : "=d" (__oldval), "=&d" (__temp) \
175 : "d" (value), "r" (__memp), \
176 "r" ((char *) __memp + 4), "0" (__oldval) \
181 #define atomic_increment_and_test(mem) \
183 if (sizeof (*(mem)) == 1) \
184 __asm __volatile ("addq%.b %#1,%1; seq %0" \
185 : "=dm" (__result), "+m" (*(mem))); \
186 else if (sizeof (*(mem)) == 2) \
187 __asm __volatile ("addq%.w %#1,%1; seq %0" \
188 : "=dm" (__result), "+m" (*(mem))); \
189 else if (sizeof (*(mem)) == 4) \
190 __asm __volatile ("addq%.l %#1,%1; seq %0" \
191 : "=dm" (__result), "+m" (*(mem))); \
194 __typeof (mem) __memp = (mem); \
195 __typeof (*(mem)) __oldval = *__memp; \
196 __typeof (*(mem)) __temp; \
197 __asm __volatile ("1: move%.l %1,%2;" \
198 " move%.l %R1,%R2;" \
202 " cas2%.l %1:%R1,%2:%R2,(%3):(%4);" \
204 : "=&dm" (__result), "=d" (__oldval), \
206 : "r" (__memp), "r" ((char *) __memp + 4), \
207 "d" (0), "1" (__oldval) \
212 #define atomic_decrement_and_test(mem) \
214 if (sizeof (*(mem)) == 1) \
215 __asm __volatile ("subq%.b %#1,%1; seq %0" \
216 : "=dm" (__result), "+m" (*(mem))); \
217 else if (sizeof (*(mem)) == 2) \
218 __asm __volatile ("subq%.w %#1,%1; seq %0" \
219 : "=dm" (__result), "+m" (*(mem))); \
220 else if (sizeof (*(mem)) == 4) \
221 __asm __volatile ("subq%.l %#1,%1; seq %0" \
222 : "=dm" (__result), "+m" (*(mem))); \
225 __typeof (mem) __memp = (mem); \
226 __typeof (*(mem)) __oldval = *__memp; \
227 __typeof (*(mem)) __temp; \
228 __asm __volatile ("1: move%.l %1,%2;" \
229 " move%.l %R1,%R2;" \
233 " cas2%.l %1:%R1,%2:%R2,(%3):(%4);" \
235 : "=&dm" (__result), "=d" (__oldval), \
237 : "r" (__memp), "r" ((char *) __memp + 4), \
238 "d" (0), "1" (__oldval) \
243 #define atomic_bit_set(mem, bit) \
244 __asm __volatile ("bfset %0{%1,#1}" \
246 : "di" (sizeof (*(mem)) * 8 - (bit) - 1))
248 #define atomic_bit_test_set(mem, bit) \
250 __asm __volatile ("bfset %1{%2,#1}; sne %0" \
251 : "=dm" (__result), "+m" (*(mem)) \
252 : "di" (sizeof (*(mem)) * 8 - (bit) - 1)); \