1 /* $OpenBSD: atomic.h,v 1.12 2019/10/28 09:41:37 visa Exp $ */
2
3 /* Public Domain */
4
5 #ifndef _MIPS64_ATOMIC_H_
6 #define _MIPS64_ATOMIC_H_
7
8 #if defined(_KERNEL)
9
10 /* wait until the bits to set are clear, and set them */
11 static __inline void
atomic_wait_and_setbits_int(volatile unsigned int * uip,unsigned int v)12 atomic_wait_and_setbits_int(volatile unsigned int *uip, unsigned int v)
13 {
14 unsigned int tmp0, tmp1;
15
16 __asm__ volatile (
17 "1: ll %0, 0(%2)\n"
18 " and %1, %0, %3\n"
19 " bnez %1, 1b\n"
20 " or %0, %3, %0\n"
21 " sc %0, 0(%2)\n"
22 " beqz %0, 1b\n"
23 " nop\n" :
24 "=&r"(tmp0), "=&r"(tmp1) :
25 "r"(uip), "r"(v) : "memory");
26 }
27
28 static __inline void
atomic_setbits_int(volatile unsigned int * uip,unsigned int v)29 atomic_setbits_int(volatile unsigned int *uip, unsigned int v)
30 {
31 unsigned int tmp;
32
33 __asm__ volatile (
34 "1: ll %0, 0(%1)\n"
35 " or %0, %2, %0\n"
36 " sc %0, 0(%1)\n"
37 " beqz %0, 1b\n"
38 " nop\n" :
39 "=&r"(tmp) :
40 "r"(uip), "r"(v) : "memory");
41 }
42
43 static __inline void
atomic_clearbits_int(volatile unsigned int * uip,unsigned int v)44 atomic_clearbits_int(volatile unsigned int *uip, unsigned int v)
45 {
46 unsigned int tmp;
47
48 __asm__ volatile (
49 "1: ll %0, 0(%1)\n"
50 " and %0, %2, %0\n"
51 " sc %0, 0(%1)\n"
52 " beqz %0, 1b\n"
53 " nop\n" :
54 "=&r"(tmp) :
55 "r"(uip), "r"(~v) : "memory");
56 }
57
58 #endif /* defined(_KERNEL) */
59
60 static inline unsigned int
_atomic_cas_uint(volatile unsigned int * p,unsigned int o,unsigned int n)61 _atomic_cas_uint(volatile unsigned int *p, unsigned int o, unsigned int n)
62 {
63 unsigned int rv, wv;
64
65 __asm__ volatile (
66 "1: ll %0, %1\n"
67 " bne %0, %4, 2f\n"
68 " move %2, %3\n"
69 " sc %2, %1\n"
70 " beqz %2, 1b\n"
71 "2: nop\n"
72 : "=&r" (rv), "+m" (*p), "=&r" (wv)
73 : "r" (n), "Ir" (o));
74
75 return (rv);
76 }
77 #define atomic_cas_uint(_p, _o, _n) _atomic_cas_uint((_p), (_o), (_n))
78
79 static inline unsigned long
_atomic_cas_ulong(volatile unsigned long * p,unsigned long o,unsigned long n)80 _atomic_cas_ulong(volatile unsigned long *p, unsigned long o, unsigned long n)
81 {
82 unsigned long rv, wv;
83
84 __asm__ volatile (
85 "1: lld %0, %1\n"
86 " bne %0, %4, 2f\n"
87 " move %2, %3\n"
88 " scd %2, %1\n"
89 " beqz %2, 1b\n"
90 "2: nop\n"
91 : "=&r" (rv), "+m" (*p), "=&r" (wv)
92 : "r" (n), "Ir" (o));
93
94 return (rv);
95 }
96 #define atomic_cas_ulong(_p, _o, _n) _atomic_cas_ulong((_p), (_o), (_n))
97
98 static inline void *
_atomic_cas_ptr(volatile void * pp,void * o,void * n)99 _atomic_cas_ptr(volatile void *pp, void *o, void *n)
100 {
101 void * volatile *p = pp;
102 void *rv, *wv;
103
104 __asm__ volatile (
105 "1: lld %0, %1\n"
106 " bne %0, %4, 2f\n"
107 " move %2, %3\n"
108 " scd %2, %1\n"
109 " beqz %2, 1b\n"
110 "2: nop\n"
111 : "=&r" (rv), "+m" (*p), "=&r" (wv)
112 : "r" (n), "Ir" (o));
113
114 return (rv);
115 }
116 #define atomic_cas_ptr(_p, _o, _n) _atomic_cas_ptr((_p), (_o), (_n))
117
118
119
120 static inline unsigned int
_atomic_swap_uint(volatile unsigned int * uip,unsigned int v)121 _atomic_swap_uint(volatile unsigned int *uip, unsigned int v)
122 {
123 unsigned int o, t;
124
125 __asm__ volatile (
126 "1: ll %0, %1\n"
127 " move %2, %3\n"
128 " sc %2, %1\n"
129 " beqz %2, 1b\n"
130 " nop\n"
131 : "=&r" (o), "+m" (*uip), "=&r" (t)
132 : "r" (v));
133
134 return (o);
135 }
136 #define atomic_swap_uint(_p, _v) _atomic_swap_uint((_p), (_v))
137
138 static inline unsigned long
_atomic_swap_ulong(volatile unsigned long * uip,unsigned long v)139 _atomic_swap_ulong(volatile unsigned long *uip, unsigned long v)
140 {
141 unsigned long o, t;
142
143 __asm__ volatile (
144 "1: lld %0, %1\n"
145 " move %2, %3\n"
146 " scd %2, %1\n"
147 " beqz %2, 1b\n"
148 " nop\n"
149 : "=&r" (o), "+m" (*uip), "=&r" (t)
150 : "r" (v));
151
152 return (o);
153 }
154 #define atomic_swap_ulong(_p, _v) _atomic_swap_ulong((_p), (_v))
155
156
157 static inline void *
_atomic_swap_ptr(volatile void * uipp,void * n)158 _atomic_swap_ptr(volatile void *uipp, void *n)
159 {
160 void * volatile *uip = uipp;
161 void *o, *t;
162
163 __asm__ volatile (
164 "1: lld %0, %1\n"
165 " move %2, %3\n"
166 " scd %2, %1\n"
167 " beqz %2, 1b\n"
168 " nop\n"
169 : "=&r" (o), "+m" (*uip), "=&r" (t)
170 : "r" (n));
171
172 return (o);
173 }
174 #define atomic_swap_ptr(_p, _n) _atomic_swap_ptr((_p), (_n))
175
176 static inline unsigned int
_atomic_add_int_nv(volatile unsigned int * uip,unsigned int v)177 _atomic_add_int_nv(volatile unsigned int *uip, unsigned int v)
178 {
179 unsigned int rv, nv;
180
181 __asm__ volatile (
182 "1: ll %0, %1\n"
183 " addu %2, %0, %3\n"
184 " sc %2, %1\n"
185 " beqz %2, 1b\n"
186 " nop\n"
187 : "=&r" (rv), "+m" (*uip), "=&r" (nv)
188 : "Ir" (v));
189
190 return (rv + v);
191 }
192 #define atomic_add_int_nv(_uip, _v) _atomic_add_int_nv((_uip), (_v))
193 #define atomic_sub_int_nv(_uip, _v) _atomic_add_int_nv((_uip), 0 - (_v))
194
195 static inline unsigned long
_atomic_add_long_nv(volatile unsigned long * uip,unsigned long v)196 _atomic_add_long_nv(volatile unsigned long *uip, unsigned long v)
197 {
198 unsigned long rv, nv;
199
200 __asm__ volatile (
201 "1: lld %0, %1\n"
202 " daddu %2, %0, %3\n"
203 " scd %2, %1\n"
204 " beqz %2, 1b\n"
205 " nop\n"
206 : "=&r" (rv), "+m" (*uip), "=&r" (nv)
207 : "Ir" (v));
208
209 return (rv + v);
210 }
211 #define atomic_add_long_nv(_uip, _v) _atomic_add_long_nv((_uip), (_v))
212 #define atomic_sub_long_nv(_uip, _v) _atomic_add_long_nv((_uip), 0UL - (_v))
213
214 #endif /* _MIPS64_ATOMIC_H_ */
215