]>
Commit | Line | Data |
---|---|---|
6d7e8eda | 1 | /* Copyright (C) 2003-2023 Free Software Foundation, Inc. |
d9a3227e | 2 | This file is part of the GNU C Library. |
d9a3227e AS |
3 | |
4 | The GNU C Library is free software; you can redistribute it and/or | |
5 | modify it under the terms of the GNU Lesser General Public | |
6 | License as published by the Free Software Foundation; either | |
7 | version 2.1 of the License, or (at your option) any later version. | |
8 | ||
9 | The GNU C Library is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | Lesser General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU Lesser General Public | |
ab84e3ff | 15 | License along with the GNU C Library. If not, see |
5a82c748 | 16 | <https://www.gnu.org/licenses/>. */ |
d9a3227e | 17 | |
1ea339b6 TR |
18 | #define __HAVE_64B_ATOMICS 1 |
19 | #define USE_ATOMIC_COMPILER_BUILTINS 0 | |
20 | ||
12d2dd70 SL |
21 | /* XXX Is this actually correct? */ |
22 | #define ATOMIC_EXCHANGE_USES_CAS 1 | |
23 | ||
d9a3227e AS |
24 | #define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ |
25 | ({ __typeof (*(mem)) __ret; \ | |
26 | __asm __volatile ("cas%.b %0,%2,%1" \ | |
945ec979 AS |
27 | : "=d" (__ret), "+m" (*(mem)) \ |
28 | : "d" (newval), "0" (oldval)); \ | |
d9a3227e AS |
29 | __ret; }) |
30 | ||
31 | #define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ | |
32 | ({ __typeof (*(mem)) __ret; \ | |
33 | __asm __volatile ("cas%.w %0,%2,%1" \ | |
945ec979 AS |
34 | : "=d" (__ret), "+m" (*(mem)) \ |
35 | : "d" (newval), "0" (oldval)); \ | |
d9a3227e AS |
36 | __ret; }) |
37 | ||
38 | #define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ | |
39 | ({ __typeof (*(mem)) __ret; \ | |
40 | __asm __volatile ("cas%.l %0,%2,%1" \ | |
945ec979 AS |
41 | : "=d" (__ret), "+m" (*(mem)) \ |
42 | : "d" (newval), "0" (oldval)); \ | |
d9a3227e AS |
43 | __ret; }) |
44 | ||
45 | # define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ | |
46 | ({ __typeof (*(mem)) __ret; \ | |
47 | __typeof (mem) __memp = (mem); \ | |
48 | __asm __volatile ("cas2%.l %0:%R0,%1:%R1,(%2):(%3)" \ | |
49 | : "=d" (__ret) \ | |
64ae9fe4 | 50 | : "d" ((__typeof (*(mem))) (newval)), "r" (__memp), \ |
d9a3227e AS |
51 | "r" ((char *) __memp + 4), "0" (oldval) \ |
52 | : "memory"); \ | |
53 | __ret; }) | |
54 | ||
25e5f254 | 55 | #define atomic_exchange_acq(mem, newvalue) \ |
d9a3227e AS |
56 | ({ __typeof (*(mem)) __result = *(mem); \ |
57 | if (sizeof (*(mem)) == 1) \ | |
58 | __asm __volatile ("1: cas%.b %0,%2,%1;" \ | |
59 | " jbne 1b" \ | |
945ec979 AS |
60 | : "=d" (__result), "+m" (*(mem)) \ |
61 | : "d" (newvalue), "0" (__result)); \ | |
d9a3227e AS |
62 | else if (sizeof (*(mem)) == 2) \ |
63 | __asm __volatile ("1: cas%.w %0,%2,%1;" \ | |
64 | " jbne 1b" \ | |
945ec979 AS |
65 | : "=d" (__result), "+m" (*(mem)) \ |
66 | : "d" (newvalue), "0" (__result)); \ | |
d9a3227e AS |
67 | else if (sizeof (*(mem)) == 4) \ |
68 | __asm __volatile ("1: cas%.l %0,%2,%1;" \ | |
69 | " jbne 1b" \ | |
945ec979 AS |
70 | : "=d" (__result), "+m" (*(mem)) \ |
71 | : "d" (newvalue), "0" (__result)); \ | |
d9a3227e AS |
72 | else \ |
73 | { \ | |
74 | __typeof (mem) __memp = (mem); \ | |
75 | __asm __volatile ("1: cas2%.l %0:%R0,%1:%R1,(%2):(%3);" \ | |
76 | " jbne 1b" \ | |
77 | : "=d" (__result) \ | |
64ae9fe4 AS |
78 | : "d" ((__typeof (*(mem))) (newvalue)), \ |
79 | "r" (__memp), "r" ((char *) __memp + 4), \ | |
80 | "0" (__result) \ | |
d9a3227e AS |
81 | : "memory"); \ |
82 | } \ | |
83 | __result; }) | |
84 | ||
85 | #define atomic_exchange_and_add(mem, value) \ | |
86 | ({ __typeof (*(mem)) __result = *(mem); \ | |
87 | __typeof (*(mem)) __temp; \ | |
88 | if (sizeof (*(mem)) == 1) \ | |
89 | __asm __volatile ("1: move%.b %0,%2;" \ | |
90 | " add%.b %3,%2;" \ | |
91 | " cas%.b %0,%2,%1;" \ | |
92 | " jbne 1b" \ | |
945ec979 | 93 | : "=d" (__result), "+m" (*(mem)), \ |
d9a3227e | 94 | "=&d" (__temp) \ |
945ec979 | 95 | : "d" (value), "0" (__result)); \ |
d9a3227e AS |
96 | else if (sizeof (*(mem)) == 2) \ |
97 | __asm __volatile ("1: move%.w %0,%2;" \ | |
98 | " add%.w %3,%2;" \ | |
99 | " cas%.w %0,%2,%1;" \ | |
100 | " jbne 1b" \ | |
945ec979 | 101 | : "=d" (__result), "+m" (*(mem)), \ |
d9a3227e | 102 | "=&d" (__temp) \ |
945ec979 | 103 | : "d" (value), "0" (__result)); \ |
d9a3227e AS |
104 | else if (sizeof (*(mem)) == 4) \ |
105 | __asm __volatile ("1: move%.l %0,%2;" \ | |
106 | " add%.l %3,%2;" \ | |
107 | " cas%.l %0,%2,%1;" \ | |
108 | " jbne 1b" \ | |
945ec979 | 109 | : "=d" (__result), "+m" (*(mem)), \ |
d9a3227e | 110 | "=&d" (__temp) \ |
945ec979 | 111 | : "d" (value), "0" (__result)); \ |
d9a3227e AS |
112 | else \ |
113 | { \ | |
114 | __typeof (mem) __memp = (mem); \ | |
115 | __asm __volatile ("1: move%.l %0,%1;" \ | |
116 | " move%.l %R0,%R1;" \ | |
a3905fd9 AS |
117 | " add%.l %R2,%R1;" \ |
118 | " addx%.l %2,%1;" \ | |
d9a3227e AS |
119 | " cas2%.l %0:%R0,%1:%R1,(%3):(%4);" \ |
120 | " jbne 1b" \ | |
121 | : "=d" (__result), "=&d" (__temp) \ | |
64ae9fe4 | 122 | : "d" ((__typeof (*(mem))) (value)), "r" (__memp), \ |
d9a3227e AS |
123 | "r" ((char *) __memp + 4), "0" (__result) \ |
124 | : "memory"); \ | |
125 | } \ | |
126 | __result; }) | |
127 | ||
128 | #define atomic_add(mem, value) \ | |
129 | (void) ({ if (sizeof (*(mem)) == 1) \ | |
130 | __asm __volatile ("add%.b %1,%0" \ | |
945ec979 AS |
131 | : "+m" (*(mem)) \ |
132 | : "id" (value)); \ | |
d9a3227e AS |
133 | else if (sizeof (*(mem)) == 2) \ |
134 | __asm __volatile ("add%.w %1,%0" \ | |
945ec979 AS |
135 | : "+m" (*(mem)) \ |
136 | : "id" (value)); \ | |
d9a3227e AS |
137 | else if (sizeof (*(mem)) == 4) \ |
138 | __asm __volatile ("add%.l %1,%0" \ | |
945ec979 AS |
139 | : "+m" (*(mem)) \ |
140 | : "id" (value)); \ | |
d9a3227e AS |
141 | else \ |
142 | { \ | |
143 | __typeof (mem) __memp = (mem); \ | |
144 | __typeof (*(mem)) __oldval = *__memp; \ | |
145 | __typeof (*(mem)) __temp; \ | |
146 | __asm __volatile ("1: move%.l %0,%1;" \ | |
147 | " move%.l %R0,%R1;" \ | |
a3905fd9 AS |
148 | " add%.l %R2,%R1;" \ |
149 | " addx%.l %2,%1;" \ | |
d9a3227e AS |
150 | " cas2%.l %0:%R0,%1:%R1,(%3):(%4);" \ |
151 | " jbne 1b" \ | |
152 | : "=d" (__oldval), "=&d" (__temp) \ | |
64ae9fe4 AS |
153 | : "d" ((__typeof (*(mem))) (value)), \ |
154 | "r" (__memp), "r" ((char *) __memp + 4), \ | |
155 | "0" (__oldval) \ | |
d9a3227e AS |
156 | : "memory"); \ |
157 | } \ | |
158 | }) | |
159 | ||
28d6ca4b AS |
160 | #define atomic_increment_and_test(mem) \ |
161 | ({ char __result; \ | |
162 | if (sizeof (*(mem)) == 1) \ | |
163 | __asm __volatile ("addq%.b %#1,%1; seq %0" \ | |
945ec979 | 164 | : "=dm" (__result), "+m" (*(mem))); \ |
28d6ca4b AS |
165 | else if (sizeof (*(mem)) == 2) \ |
166 | __asm __volatile ("addq%.w %#1,%1; seq %0" \ | |
945ec979 | 167 | : "=dm" (__result), "+m" (*(mem))); \ |
28d6ca4b AS |
168 | else if (sizeof (*(mem)) == 4) \ |
169 | __asm __volatile ("addq%.l %#1,%1; seq %0" \ | |
945ec979 | 170 | : "=dm" (__result), "+m" (*(mem))); \ |
28d6ca4b AS |
171 | else \ |
172 | { \ | |
173 | __typeof (mem) __memp = (mem); \ | |
174 | __typeof (*(mem)) __oldval = *__memp; \ | |
175 | __typeof (*(mem)) __temp; \ | |
176 | __asm __volatile ("1: move%.l %1,%2;" \ | |
177 | " move%.l %R1,%R2;" \ | |
a3905fd9 AS |
178 | " addq%.l %#1,%R2;" \ |
179 | " addx%.l %5,%2;" \ | |
28d6ca4b AS |
180 | " seq %0;" \ |
181 | " cas2%.l %1:%R1,%2:%R2,(%3):(%4);" \ | |
182 | " jbne 1b" \ | |
183 | : "=&dm" (__result), "=d" (__oldval), \ | |
184 | "=&d" (__temp) \ | |
185 | : "r" (__memp), "r" ((char *) __memp + 4), \ | |
186 | "d" (0), "1" (__oldval) \ | |
187 | : "memory"); \ | |
188 | } \ | |
189 | __result; }) | |
190 | ||
d9a3227e AS |
191 | #define atomic_decrement_and_test(mem) \ |
192 | ({ char __result; \ | |
193 | if (sizeof (*(mem)) == 1) \ | |
28d6ca4b | 194 | __asm __volatile ("subq%.b %#1,%1; seq %0" \ |
945ec979 | 195 | : "=dm" (__result), "+m" (*(mem))); \ |
d9a3227e | 196 | else if (sizeof (*(mem)) == 2) \ |
28d6ca4b | 197 | __asm __volatile ("subq%.w %#1,%1; seq %0" \ |
945ec979 | 198 | : "=dm" (__result), "+m" (*(mem))); \ |
d9a3227e | 199 | else if (sizeof (*(mem)) == 4) \ |
28d6ca4b | 200 | __asm __volatile ("subq%.l %#1,%1; seq %0" \ |
945ec979 | 201 | : "=dm" (__result), "+m" (*(mem))); \ |
d9a3227e AS |
202 | else \ |
203 | { \ | |
97b729d3 | 204 | __typeof (mem) __memp = (mem); \ |
d9a3227e AS |
205 | __typeof (*(mem)) __oldval = *__memp; \ |
206 | __typeof (*(mem)) __temp; \ | |
207 | __asm __volatile ("1: move%.l %1,%2;" \ | |
208 | " move%.l %R1,%R2;" \ | |
a3905fd9 AS |
209 | " subq%.l %#1,%R2;" \ |
210 | " subx%.l %5,%2;" \ | |
28d6ca4b | 211 | " seq %0;" \ |
d9a3227e AS |
212 | " cas2%.l %1:%R1,%2:%R2,(%3):(%4);" \ |
213 | " jbne 1b" \ | |
214 | : "=&dm" (__result), "=d" (__oldval), \ | |
215 | "=&d" (__temp) \ | |
216 | : "r" (__memp), "r" ((char *) __memp + 4), \ | |
217 | "d" (0), "1" (__oldval) \ | |
218 | : "memory"); \ | |
219 | } \ | |
220 | __result; }) | |
221 | ||
222 | #define atomic_bit_set(mem, bit) \ | |
223 | __asm __volatile ("bfset %0{%1,#1}" \ | |
945ec979 AS |
224 | : "+m" (*(mem)) \ |
225 | : "di" (sizeof (*(mem)) * 8 - (bit) - 1)) | |
d9a3227e AS |
226 | |
227 | #define atomic_bit_test_set(mem, bit) \ | |
228 | ({ char __result; \ | |
229 | __asm __volatile ("bfset %1{%2,#1}; sne %0" \ | |
945ec979 AS |
230 | : "=dm" (__result), "+m" (*(mem)) \ |
231 | : "di" (sizeof (*(mem)) * 8 - (bit) - 1)); \ | |
d9a3227e | 232 | __result; }) |