Move m68k from ports to libc
[jlayton/glibc.git] / sysdeps / m68k / m680x0 / m68020 / bits / atomic.h
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.
4
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.
9
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.
14
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/>.  */
18
19 #include <stdint.h>
20
21
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;
26
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;
31
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;
36
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;
41
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;
46
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));                         \
52      __ret; })
53
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));                         \
59      __ret; })
60
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));                         \
66      __ret; })
67
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)"                      \
72                        : "=d" (__ret)                                         \
73                        : "d" (newval), "r" (__memp),                          \
74                          "r" ((char *) __memp + 4), "0" (oldval)              \
75                        : "memory");                                           \
76      __ret; })
77
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;"                                \
82                          "   jbne 1b"                                         \
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;"                                \
87                          "   jbne 1b"                                         \
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;"                                \
92                          "   jbne 1b"                                         \
93                          : "=d" (__result), "+m" (*(mem))                     \
94                          : "d" (newvalue), "0" (__result));                   \
95      else                                                                     \
96        {                                                                      \
97          __typeof (mem) __memp = (mem);                                       \
98          __asm __volatile ("1: cas2%.l %0:%R0,%1:%R1,(%2):(%3);"              \
99                            "   jbne 1b"                                       \
100                            : "=d" (__result)                                  \
101                            : "d" (newvalue), "r" (__memp),                    \
102                              "r" ((char *) __memp + 4), "0" (__result)        \
103                            : "memory");                                       \
104        }                                                                      \
105      __result; })
106
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;"                                  \
112                          "   add%.b %3,%2;"                                   \
113                          "   cas%.b %0,%2,%1;"                                \
114                          "   jbne 1b"                                         \
115                          : "=d" (__result), "+m" (*(mem)),                    \
116                            "=&d" (__temp)                                     \
117                          : "d" (value), "0" (__result));                      \
118      else if (sizeof (*(mem)) == 2)                                           \
119        __asm __volatile ("1: move%.w %0,%2;"                                  \
120                          "   add%.w %3,%2;"                                   \
121                          "   cas%.w %0,%2,%1;"                                \
122                          "   jbne 1b"                                         \
123                          : "=d" (__result), "+m" (*(mem)),                    \
124                            "=&d" (__temp)                                     \
125                          : "d" (value), "0" (__result));                      \
126      else if (sizeof (*(mem)) == 4)                                           \
127        __asm __volatile ("1: move%.l %0,%2;"                                  \
128                          "   add%.l %3,%2;"                                   \
129                          "   cas%.l %0,%2,%1;"                                \
130                          "   jbne 1b"                                         \
131                          : "=d" (__result), "+m" (*(mem)),                    \
132                            "=&d" (__temp)                                     \
133                          : "d" (value), "0" (__result));                      \
134      else                                                                     \
135        {                                                                      \
136          __typeof (mem) __memp = (mem);                                       \
137          __asm __volatile ("1: move%.l %0,%1;"                                \
138                            "   move%.l %R0,%R1;"                              \
139                            "   add%.l %2,%1;"                                 \
140                            "   addx%.l %R2,%R1;"                              \
141                            "   cas2%.l %0:%R0,%1:%R1,(%3):(%4);"              \
142                            "   jbne 1b"                                       \
143                            : "=d" (__result), "=&d" (__temp)                  \
144                            : "d" (value), "r" (__memp),                       \
145                              "r" ((char *) __memp + 4), "0" (__result)        \
146                            : "memory");                                       \
147        }                                                                      \
148      __result; })
149
150 #define atomic_add(mem, value) \
151   (void) ({ if (sizeof (*(mem)) == 1)                                         \
152               __asm __volatile ("add%.b %1,%0"                                \
153                                 : "+m" (*(mem))                               \
154                                 : "id" (value));                              \
155             else if (sizeof (*(mem)) == 2)                                    \
156               __asm __volatile ("add%.w %1,%0"                                \
157                                 : "+m" (*(mem))                               \
158                                 : "id" (value));                              \
159             else if (sizeof (*(mem)) == 4)                                    \
160               __asm __volatile ("add%.l %1,%0"                                \
161                                 : "+m" (*(mem))                               \
162                                 : "id" (value));                              \
163             else                                                              \
164               {                                                               \
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;"                       \
170                                   "   add%.l %2,%1;"                          \
171                                   "   addx%.l %R2,%R1;"                       \
172                                   "   cas2%.l %0:%R0,%1:%R1,(%3):(%4);"       \
173                                   "   jbne 1b"                                \
174                                   : "=d" (__oldval), "=&d" (__temp)           \
175                                   : "d" (value), "r" (__memp),                \
176                                     "r" ((char *) __memp + 4), "0" (__oldval) \
177                                   : "memory");                                \
178               }                                                               \
179             })
180
181 #define atomic_increment_and_test(mem) \
182   ({ char __result;                                                           \
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)));                  \
192      else                                                                     \
193        {                                                                      \
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;"                              \
199                            "   addq%.l %#1,%2;"                               \
200                            "   addx%.l %5,%R2;"                               \
201                            "   seq %0;"                                       \
202                            "   cas2%.l %1:%R1,%2:%R2,(%3):(%4);"              \
203                            "   jbne 1b"                                       \
204                            : "=&dm" (__result), "=d" (__oldval),              \
205                              "=&d" (__temp)                                   \
206                            : "r" (__memp), "r" ((char *) __memp + 4),         \
207                              "d" (0), "1" (__oldval)                          \
208                            : "memory");                                       \
209        }                                                                      \
210      __result; })
211
212 #define atomic_decrement_and_test(mem) \
213   ({ char __result;                                                           \
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)));                  \
223      else                                                                     \
224        {                                                                      \
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;"                              \
230                            "   subq%.l %#1,%2;"                               \
231                            "   subx%.l %5,%R2;"                               \
232                            "   seq %0;"                                       \
233                            "   cas2%.l %1:%R1,%2:%R2,(%3):(%4);"              \
234                            "   jbne 1b"                                       \
235                            : "=&dm" (__result), "=d" (__oldval),              \
236                              "=&d" (__temp)                                   \
237                            : "r" (__memp), "r" ((char *) __memp + 4),         \
238                              "d" (0), "1" (__oldval)                          \
239                            : "memory");                                       \
240        }                                                                      \
241      __result; })
242
243 #define atomic_bit_set(mem, bit) \
244   __asm __volatile ("bfset %0{%1,#1}"                                         \
245                     : "+m" (*(mem))                                           \
246                     : "di" (sizeof (*(mem)) * 8 - (bit) - 1))
247
248 #define atomic_bit_test_set(mem, bit) \
249   ({ char __result;                                                           \
250      __asm __volatile ("bfset %1{%2,#1}; sne %0"                              \
251                        : "=dm" (__result), "+m" (*(mem))                      \
252                        : "di" (sizeof (*(mem)) * 8 - (bit) - 1));             \
253      __result; })