OSDN Git Service

49163a20d9a9132fcb9804cd57c594c184f62542
[uclinux-h8/uClibc.git] / libc / sysdeps / linux / xtensa / bits / atomic.h
1 /* Copyright (C) 2012 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
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
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
17    Boston, MA 02110-1301, USA.  */
18
19 #ifndef _BITS_ATOMIC_H
20 #define _BITS_ATOMIC_H  1
21
22 #include <inttypes.h>
23
24 typedef int32_t atomic32_t;
25 typedef uint32_t uatomic32_t;
26 typedef int_fast32_t atomic_fast32_t;
27 typedef uint_fast32_t uatomic_fast32_t;
28
29 typedef int64_t atomic64_t;
30 typedef uint64_t uatomic64_t;
31 typedef int_fast64_t atomic_fast64_t;
32 typedef uint_fast64_t uatomic_fast64_t;
33
34 typedef intptr_t atomicptr_t;
35 typedef uintptr_t uatomicptr_t;
36 typedef intmax_t atomic_max_t;
37 typedef uintmax_t uatomic_max_t;
38
39
40 /* Xtensa has only a 32-bit form of a store-conditional instruction.  */
41
42 #define __arch_compare_and_exchange_bool_8_acq(mem, newval, oldval) \
43       (abort (), 0)
44
45 #define __arch_compare_and_exchange_bool_16_acq(mem, newval, oldval) \
46       (abort (), 0)
47
48 #define __arch_compare_and_exchange_bool_8_rel(mem, newval, oldval) \
49       (abort (), 0)
50
51 #define __arch_compare_and_exchange_bool_16_rel(mem, newval, oldval) \
52       (abort (), 0)
53
54 /* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
55    Return the old *MEM value.  */
56
57 #define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval)  \
58   ({__typeof__(*(mem)) __tmp, __value;                               \
59     __asm__ __volatile__(                                            \
60       "1:     l32i    %1, %2, 0               \n"                    \
61       "       bne     %1, %4, 2f              \n"                    \
62       "       wsr     %1, SCOMPARE1           \n"                    \
63       "       mov     %0, %1                  \n"                    \
64       "       mov     %1, %3                  \n"                    \
65       "       s32c1i  %1, %2, 0               \n"                    \
66       "       bne     %0, %1, 1b              \n"                    \
67       "2:                                     \n"                    \
68       : "=&a" (__value), "=&a" (__tmp)                               \
69       : "a" (mem), "a" (newval), "a" (oldval)                        \
70       : "memory" );                                                  \
71     __tmp;                                                           \
72   })
73
74 /* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
75    Return zero if *MEM was changed or non-zero if no exchange happened.  */
76
77 #define __arch_compare_and_exchange_bool_32_acq(mem, newval, oldval) \
78   ({__typeof__(*(mem)) __tmp, __value;                               \
79     __asm__ __volatile__(                                            \
80       "1:     l32i    %0, %2, 0               \n"                    \
81       "       sub     %1, %4, %0              \n"                    \
82       "       bnez    %1, 2f                  \n"                    \
83       "       wsr     %0, SCOMPARE1           \n"                    \
84       "       mov     %1, %3                  \n"                    \
85       "       s32c1i  %1, %2, 0               \n"                    \
86       "       bne     %0, %1, 1b              \n"                    \
87       "       movi    %1, 0                   \n"                    \
88       "2:                                     \n"                    \
89       : "=&a" (__value), "=&a" (__tmp)                               \
90       : "a" (mem), "a" (newval), "a" (oldval)                        \
91       : "memory" );                                                  \
92     __tmp != 0;                                                      \
93   })
94
95 /* Store NEWVALUE in *MEM and return the old value.  */
96
97 #define __arch_exchange_32_acq(mem, newval)                          \
98   ({__typeof__(*(mem)) __tmp, __value;                               \
99     __asm__ __volatile__(                                            \
100       "1:     l32i    %0, %2, 0               \n"                    \
101       "       wsr     %0, SCOMPARE1           \n"                    \
102       "       mov     %1, %3                  \n"                    \
103       "       s32c1i  %1, %2, 0               \n"                    \
104       "       bne     %0, %1, 1b              \n"                    \
105       : "=&a" (__value), "=&a" (__tmp)                               \
106       : "a" (mem), "a" (newval)                                      \
107       : "memory" );                                                  \
108     __tmp;                                                           \
109   })
110
111 /* Add VALUE to *MEM and return the old value of *MEM.  */
112
113 #define __arch_atomic_exchange_and_add_32(mem, value)                \
114   ({__typeof__(*(mem)) __tmp, __value;                               \
115     __asm__ __volatile__(                                            \
116       "1:     l32i    %0, %2, 0               \n"                    \
117       "       wsr     %0, SCOMPARE1           \n"                    \
118       "       add     %1, %0, %3              \n"                    \
119       "       s32c1i  %1, %2, 0               \n"                    \
120       "       bne     %0, %1, 1b              \n"                    \
121       : "=&a" (__value), "=&a" (__tmp)                               \
122       : "a" (mem), "a" (value)                                       \
123       : "memory" );                                                  \
124     __tmp;                                                           \
125   })
126
127 /* Subtract VALUE from *MEM and return the old value of *MEM.  */
128
129 #define __arch_atomic_exchange_and_sub_32(mem, value)                \
130   ({__typeof__(*(mem)) __tmp, __value;                               \
131     __asm__ __volatile__(                                            \
132       "1:     l32i    %0, %2, 0               \n"                    \
133       "       wsr     %0, SCOMPARE1           \n"                    \
134       "       sub     %1, %0, %3              \n"                    \
135       "       s32c1i  %1, %2, 0               \n"                    \
136       "       bne     %0, %1, 1b              \n"                    \
137       : "=&a" (__value), "=&a" (__tmp)                               \
138       : "a" (mem), "a" (value)                                       \
139       : "memory" );                                                  \
140     __tmp;                                                           \
141   })
142
143 /* Decrement *MEM if it is > 0, and return the old value.  */
144
145 #define __arch_atomic_decrement_if_positive_32(mem)                  \
146   ({__typeof__(*(mem)) __tmp, __value;                               \
147     __asm__ __volatile__(                                            \
148       "1:     l32i    %0, %2, 0               \n"                    \
149       "       blti    %0, 1, 2f               \n"                    \
150       "       wsr     %0, SCOMPARE1           \n"                    \
151       "       addi    %1, %0, -1              \n"                    \
152       "       s32c1i  %1, %2, 0               \n"                    \
153       "       bne     %0, %1, 1b              \n"                    \
154       "2:                                     \n"                    \
155       : "=&a" (__value), "=&a" (__tmp)                               \
156       : "a" (mem)                                                    \
157       : "memory" );                                                  \
158     __tmp;                                                           \
159   })
160
161
162 /* These are the preferred public interfaces: */
163
164 #define atomic_compare_and_exchange_val_acq(mem, newval, oldval)     \
165   ({                                                                 \
166     if (sizeof (*mem) != 4)                                          \
167       abort();                                                       \
168     __arch_compare_and_exchange_val_32_acq(mem, newval, oldval);     \
169   })
170
171 #define atomic_exchange_acq(mem, newval)                             \
172   ({                                                                 \
173     if (sizeof(*(mem)) != 4)                                         \
174       abort();                                                       \
175     __arch_exchange_32_acq(mem, newval);                             \
176   })
177
178 #define atomic_exchange_and_add(mem, newval)                         \
179   ({                                                                 \
180     if (sizeof(*(mem)) != 4)                                         \
181       abort();                                                       \
182     __arch_atomic_exchange_and_add_32(mem, newval);                  \
183   })
184
185 #define atomic_exchange_and_sub(mem, newval)                         \
186   ({                                                                 \
187     if (sizeof(*(mem)) != 4)                                         \
188       abort();                                                       \
189     __arch_atomic_exchange_and_sub_32(mem, newval);                  \
190   })
191
192 #define atomic_decrement_if_positive(mem)                            \
193   ({                                                                 \
194     if (sizeof(*(mem)) != 4)                                         \
195       abort();                                                       \
196     __arch_atomic_decrement_if_positive_32(mem);                     \
197   })
198
199
200 # define __arch_compare_and_exchange_bool_64_acq(mem, newval, oldval) \
201     (abort (), 0)
202
203 # define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
204     (abort (), (__typeof (*mem)) 0)
205
206 # define __arch_compare_and_exchange_bool_64_rel(mem, newval, oldval) \
207     (abort (), 0)
208
209 # define __arch_compare_and_exchange_val_64_rel(mem, newval, oldval) \
210     (abort (), (__typeof (*mem)) 0)
211
212 # define __arch_atomic_exchange_64_acq(mem, value) \
213     ({ abort (); (*mem) = (value); })
214
215 # define __arch_atomic_exchange_64_rel(mem, value) \
216     ({ abort (); (*mem) = (value); })
217
218 # define __arch_atomic_exchange_and_add_64(mem, value) \
219     ({ abort (); (*mem) = (value); })
220
221 # define __arch_atomic_increment_val_64(mem) \
222     ({ abort (); (*mem)++; })
223
224 # define __arch_atomic_decrement_val_64(mem) \
225     ({ abort (); (*mem)--; })
226
227 # define __arch_atomic_decrement_if_positive_64(mem) \
228     ({ abort (); (*mem)--; })
229
230
231
232 #endif /* _BITS_ATOMIC_H */
233