GNU Linux-libre 6.1.90-gnu
[releases.git] / arch / csky / include / asm / cmpxchg.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2
3 #ifndef __ASM_CSKY_CMPXCHG_H
4 #define __ASM_CSKY_CMPXCHG_H
5
6 #ifdef CONFIG_SMP
7 #include <linux/bug.h>
8 #include <asm/barrier.h>
9
10 #define __xchg_relaxed(new, ptr, size)                          \
11 ({                                                              \
12         __typeof__(ptr) __ptr = (ptr);                          \
13         __typeof__(new) __new = (new);                          \
14         __typeof__(*(ptr)) __ret;                               \
15         unsigned long tmp;                                      \
16         switch (size) {                                         \
17         case 2: {                                               \
18                 u32 ret;                                        \
19                 u32 shif = ((ulong)__ptr & 2) ? 16 : 0;         \
20                 u32 mask = 0xffff << shif;                      \
21                 __ptr = (__typeof__(ptr))((ulong)__ptr & ~2);   \
22                 __asm__ __volatile__ (                          \
23                         "1:     ldex.w %0, (%4)\n"              \
24                         "       and    %1, %0, %2\n"            \
25                         "       or     %1, %1, %3\n"            \
26                         "       stex.w %1, (%4)\n"              \
27                         "       bez    %1, 1b\n"                \
28                         : "=&r" (ret), "=&r" (tmp)              \
29                         : "r" (~mask),                          \
30                           "r" ((u32)__new << shif),             \
31                           "r" (__ptr)                           \
32                         : "memory");                            \
33                 __ret = (__typeof__(*(ptr)))                    \
34                         ((ret & mask) >> shif);                 \
35                 break;                                          \
36         }                                                       \
37         case 4:                                                 \
38                 asm volatile (                                  \
39                 "1:     ldex.w          %0, (%3) \n"            \
40                 "       mov             %1, %2   \n"            \
41                 "       stex.w          %1, (%3) \n"            \
42                 "       bez             %1, 1b   \n"            \
43                         : "=&r" (__ret), "=&r" (tmp)            \
44                         : "r" (__new), "r"(__ptr)               \
45                         :);                                     \
46                 break;                                          \
47         default:                                                \
48                 BUILD_BUG();                                    \
49         }                                                       \
50         __ret;                                                  \
51 })
52
53 #define arch_xchg_relaxed(ptr, x) \
54                 (__xchg_relaxed((x), (ptr), sizeof(*(ptr))))
55
56 #define __cmpxchg_relaxed(ptr, old, new, size)                  \
57 ({                                                              \
58         __typeof__(ptr) __ptr = (ptr);                          \
59         __typeof__(new) __new = (new);                          \
60         __typeof__(new) __tmp;                                  \
61         __typeof__(old) __old = (old);                          \
62         __typeof__(*(ptr)) __ret;                               \
63         switch (size) {                                         \
64         case 4:                                                 \
65                 asm volatile (                                  \
66                 "1:     ldex.w          %0, (%3) \n"            \
67                 "       cmpne           %0, %4   \n"            \
68                 "       bt              2f       \n"            \
69                 "       mov             %1, %2   \n"            \
70                 "       stex.w          %1, (%3) \n"            \
71                 "       bez             %1, 1b   \n"            \
72                 "2:                              \n"            \
73                         : "=&r" (__ret), "=&r" (__tmp)          \
74                         : "r" (__new), "r"(__ptr), "r"(__old)   \
75                         :);                                     \
76                 break;                                          \
77         default:                                                \
78                 BUILD_BUG();                                    \
79         }                                                       \
80         __ret;                                                  \
81 })
82
83 #define arch_cmpxchg_relaxed(ptr, o, n) \
84         (__cmpxchg_relaxed((ptr), (o), (n), sizeof(*(ptr))))
85
86 #define __cmpxchg_acquire(ptr, old, new, size)                  \
87 ({                                                              \
88         __typeof__(ptr) __ptr = (ptr);                          \
89         __typeof__(new) __new = (new);                          \
90         __typeof__(new) __tmp;                                  \
91         __typeof__(old) __old = (old);                          \
92         __typeof__(*(ptr)) __ret;                               \
93         switch (size) {                                         \
94         case 4:                                                 \
95                 asm volatile (                                  \
96                 "1:     ldex.w          %0, (%3) \n"            \
97                 "       cmpne           %0, %4   \n"            \
98                 "       bt              2f       \n"            \
99                 "       mov             %1, %2   \n"            \
100                 "       stex.w          %1, (%3) \n"            \
101                 "       bez             %1, 1b   \n"            \
102                 ACQUIRE_FENCE                                   \
103                 "2:                              \n"            \
104                         : "=&r" (__ret), "=&r" (__tmp)          \
105                         : "r" (__new), "r"(__ptr), "r"(__old)   \
106                         :);                                     \
107                 break;                                          \
108         default:                                                \
109                 BUILD_BUG();                                    \
110         }                                                       \
111         __ret;                                                  \
112 })
113
114 #define arch_cmpxchg_acquire(ptr, o, n) \
115         (__cmpxchg_acquire((ptr), (o), (n), sizeof(*(ptr))))
116
117 #define __cmpxchg(ptr, old, new, size)                          \
118 ({                                                              \
119         __typeof__(ptr) __ptr = (ptr);                          \
120         __typeof__(new) __new = (new);                          \
121         __typeof__(new) __tmp;                                  \
122         __typeof__(old) __old = (old);                          \
123         __typeof__(*(ptr)) __ret;                               \
124         switch (size) {                                         \
125         case 4:                                                 \
126                 asm volatile (                                  \
127                 RELEASE_FENCE                                   \
128                 "1:     ldex.w          %0, (%3) \n"            \
129                 "       cmpne           %0, %4   \n"            \
130                 "       bt              2f       \n"            \
131                 "       mov             %1, %2   \n"            \
132                 "       stex.w          %1, (%3) \n"            \
133                 "       bez             %1, 1b   \n"            \
134                 FULL_FENCE                                      \
135                 "2:                              \n"            \
136                         : "=&r" (__ret), "=&r" (__tmp)          \
137                         : "r" (__new), "r"(__ptr), "r"(__old)   \
138                         :);                                     \
139                 break;                                          \
140         default:                                                \
141                 BUILD_BUG();                                    \
142         }                                                       \
143         __ret;                                                  \
144 })
145
146 #define arch_cmpxchg(ptr, o, n)                                 \
147         (__cmpxchg((ptr), (o), (n), sizeof(*(ptr))))
148
149 #define arch_cmpxchg_local(ptr, o, n)                           \
150         (__cmpxchg_relaxed((ptr), (o), (n), sizeof(*(ptr))))
151 #else
152 #include <asm-generic/cmpxchg.h>
153 #endif
154
155 #endif /* __ASM_CSKY_CMPXCHG_H */