1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // RISC-V's atomic operations have two bits, aq ("acquire") and rl ("release"),
6 // which may be toggled on and off. Their precise semantics are defined in
7 // section 6.3 of the specification, but the basic idea is as follows:
8 //
9 // - If neither aq nor rl is set, the CPU may reorder the atomic arbitrarily.
10 // It guarantees only that it will execute atomically.
11 //
12 // - If aq is set, the CPU may move the instruction backward, but not forward.
13 //
14 // - If rl is set, the CPU may move the instruction forward, but not backward.
15 //
16 // - If both are set, the CPU may not reorder the instruction at all.
17 //
18 // These four modes correspond to other well-known memory models on other CPUs.
19 // On ARM, aq corresponds to a dmb ishst, aq+rl corresponds to a dmb ish. On
20 // Intel, aq corresponds to an lfence, rl to an sfence, and aq+rl to an mfence
21 // (or a lock prefix).
22 //
23 // Go's memory model requires that
24 // - if a read happens after a write, the read must observe the write, and
25 // that
26 // - if a read happens concurrently with a write, the read may observe the
27 // write.
28 // aq is sufficient to guarantee this, so that's what we use here. (This jibes
29 // with ARM, which uses dmb ishst.)
30
31 #include "textflag.h"
32
33 // func Cas(ptr *uint64, old, new uint64) bool
34 // Atomically:
35 // if *ptr == old {
36 // *ptr = new
37 // return true
38 // } else {
39 // return false
40 // }
41 TEXT ·Cas(SB), NOSPLIT, $0-17
42 MOV ptr+0(FP), A0
43 MOVW old+8(FP), A1
44 MOVW new+12(FP), A2
45 cas_again:
46 LRW (A0), A3
47 BNE A3, A1, cas_fail
48 SCW A2, (A0), A4
49 BNE A4, ZERO, cas_again
50 MOV $1, A0
51 MOVB A0, ret+16(FP)
52 RET
53 cas_fail:
54 MOV $0, A0
55 MOV A0, ret+16(FP)
56 RET
57
58 // func Cas64(ptr *uint64, old, new uint64) bool
59 TEXT ·Cas64(SB), NOSPLIT, $0-25
60 MOV ptr+0(FP), A0
61 MOV old+8(FP), A1
62 MOV new+16(FP), A2
63 cas_again:
64 LRD (A0), A3
65 BNE A3, A1, cas_fail
66 SCD A2, (A0), A4
67 BNE A4, ZERO, cas_again
68 MOV $1, A0
69 MOVB A0, ret+24(FP)
70 RET
71 cas_fail:
72 MOVB ZERO, ret+24(FP)
73 RET
74
75 // func Load(ptr *uint32) uint32
76 TEXT ·Load(SB),NOSPLIT|NOFRAME,$0-12
77 MOV ptr+0(FP), A0
78 LRW (A0), A0
79 MOVW A0, ret+8(FP)
80 RET
81
82 // func Load8(ptr *uint8) uint8
83 TEXT ·Load8(SB),NOSPLIT|NOFRAME,$0-9
84 MOV ptr+0(FP), A0
85 FENCE
86 MOVBU (A0), A1
87 FENCE
88 MOVB A1, ret+8(FP)
89 RET
90
91 // func Load64(ptr *uint64) uint64
92 TEXT ·Load64(SB),NOSPLIT|NOFRAME,$0-16
93 MOV ptr+0(FP), A0
94 LRD (A0), A0
95 MOV A0, ret+8(FP)
96 RET
97
98 // func Store(ptr *uint32, val uint32)
99 TEXT ·Store(SB), NOSPLIT, $0-12
100 MOV ptr+0(FP), A0
101 MOVW val+8(FP), A1
102 AMOSWAPW A1, (A0), ZERO
103 RET
104
105 // func Store8(ptr *uint8, val uint8)
106 TEXT ·Store8(SB), NOSPLIT, $0-9
107 MOV ptr+0(FP), A0
108 MOVBU val+8(FP), A1
109 FENCE
110 MOVB A1, (A0)
111 FENCE
112 RET
113
114 // func Store64(ptr *uint64, val uint64)
115 TEXT ·Store64(SB), NOSPLIT, $0-16
116 MOV ptr+0(FP), A0
117 MOV val+8(FP), A1
118 AMOSWAPD A1, (A0), ZERO
119 RET
120
121 TEXT ·Casp1(SB), NOSPLIT, $0-25
122 JMP ·Cas64(SB)
123
124 TEXT ·Casint32(SB),NOSPLIT,$0-17
125 JMP ·Cas(SB)
126
127 TEXT ·Casint64(SB),NOSPLIT,$0-25
128 JMP ·Cas64(SB)
129
130 TEXT ·Casuintptr(SB),NOSPLIT,$0-25
131 JMP ·Cas64(SB)
132
133 TEXT ·CasRel(SB), NOSPLIT, $0-17
134 JMP ·Cas(SB)
135
136 TEXT ·Loaduintptr(SB),NOSPLIT,$0-16
137 JMP ·Load64(SB)
138
139 TEXT ·Storeint32(SB),NOSPLIT,$0-12
140 JMP ·Store(SB)
141
142 TEXT ·Storeint64(SB),NOSPLIT,$0-16
143 JMP ·Store64(SB)
144
145 TEXT ·Storeuintptr(SB),NOSPLIT,$0-16
146 JMP ·Store64(SB)
147
148 TEXT ·Loaduint(SB),NOSPLIT,$0-16
149 JMP ·Loaduintptr(SB)
150
151 TEXT ·Loadint32(SB),NOSPLIT,$0-12
152 JMP ·Load(SB)
153
154 TEXT ·Loadint64(SB),NOSPLIT,$0-16
155 JMP ·Load64(SB)
156
157 TEXT ·Xaddint32(SB),NOSPLIT,$0-20
158 JMP ·Xadd(SB)
159
160 TEXT ·Xaddint64(SB),NOSPLIT,$0-24
161 MOV ptr+0(FP), A0
162 MOV delta+8(FP), A1
163 AMOADDD A1, (A0), A0
164 ADD A0, A1, A0
165 MOVW A0, ret+16(FP)
166 RET
167
168 TEXT ·LoadAcq(SB),NOSPLIT|NOFRAME,$0-12
169 JMP ·Load(SB)
170
171 TEXT ·LoadAcq64(SB),NOSPLIT|NOFRAME,$0-16
172 JMP ·Load64(SB)
173
174 TEXT ·LoadAcquintptr(SB),NOSPLIT|NOFRAME,$0-16
175 JMP ·Load64(SB)
176
177 // func Loadp(ptr unsafe.Pointer) unsafe.Pointer
178 TEXT ·Loadp(SB),NOSPLIT,$0-16
179 JMP ·Load64(SB)
180
181 // func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer)
182 TEXT ·StorepNoWB(SB), NOSPLIT, $0-16
183 JMP ·Store64(SB)
184
185 TEXT ·StoreRel(SB), NOSPLIT, $0-12
186 JMP ·Store(SB)
187
188 TEXT ·StoreRel64(SB), NOSPLIT, $0-16
189 JMP ·Store64(SB)
190
191 TEXT ·StoreReluintptr(SB), NOSPLIT, $0-16
192 JMP ·Store64(SB)
193
194 // func Xchg(ptr *uint32, new uint32) uint32
195 TEXT ·Xchg(SB), NOSPLIT, $0-20
196 MOV ptr+0(FP), A0
197 MOVW new+8(FP), A1
198 AMOSWAPW A1, (A0), A1
199 MOVW A1, ret+16(FP)
200 RET
201
202 // func Xchg8(ptr *uint8, new uint8) uint8
203 TEXT ·Xchg8(SB), NOSPLIT, $0-17
204 MOV ptr+0(FP), A0
205 MOVBU new+8(FP), A1
206 AND $3, A0, A2
207 SLL $3, A2
208 MOV $255, A4
209 SLL A2, A4
210 NOT A4
211 AND $~3, A0
212 SLL A2, A1
213 xchg8_again:
214 LRW (A0), A5
215 AND A4, A5, A3
216 OR A1, A3
217 SCW A3, (A0), A6
218 BNEZ A6, xchg8_again
219 SRL A2, A5
220 MOVB A5, ret+16(FP)
221 RET
222
223 // func Xchg64(ptr *uint64, new uint64) uint64
224 TEXT ·Xchg64(SB), NOSPLIT, $0-24
225 MOV ptr+0(FP), A0
226 MOV new+8(FP), A1
227 AMOSWAPD A1, (A0), A1
228 MOV A1, ret+16(FP)
229 RET
230
231 // Atomically:
232 // *val += delta;
233 // return *val;
234
235 // func Xadd(ptr *uint32, delta int32) uint32
236 TEXT ·Xadd(SB), NOSPLIT, $0-20
237 MOV ptr+0(FP), A0
238 MOVW delta+8(FP), A1
239 AMOADDW A1, (A0), A2
240 ADD A2,A1,A0
241 MOVW A0, ret+16(FP)
242 RET
243
244 // func Xadd64(ptr *uint64, delta int64) uint64
245 TEXT ·Xadd64(SB), NOSPLIT, $0-24
246 MOV ptr+0(FP), A0
247 MOV delta+8(FP), A1
248 AMOADDD A1, (A0), A2
249 ADD A2, A1, A0
250 MOV A0, ret+16(FP)
251 RET
252
253 // func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
254 TEXT ·Xadduintptr(SB), NOSPLIT, $0-24
255 JMP ·Xadd64(SB)
256
257 // func Xchgint32(ptr *int32, new int32) int32
258 TEXT ·Xchgint32(SB), NOSPLIT, $0-20
259 JMP ·Xchg(SB)
260
261 // func Xchgint64(ptr *int64, new int64) int64
262 TEXT ·Xchgint64(SB), NOSPLIT, $0-24
263 JMP ·Xchg64(SB)
264
265 // func Xchguintptr(ptr *uintptr, new uintptr) uintptr
266 TEXT ·Xchguintptr(SB), NOSPLIT, $0-24
267 JMP ·Xchg64(SB)
268
269 // func And8(ptr *uint8, val uint8)
270 TEXT ·And8(SB), NOSPLIT, $0-9
271 MOV ptr+0(FP), A0
272 MOVBU val+8(FP), A1
273 AND $3, A0, A2
274 AND $-4, A0
275 SLL $3, A2
276 XOR $255, A1
277 SLL A2, A1
278 XOR $-1, A1
279 AMOANDW A1, (A0), ZERO
280 RET
281
282 // func Or8(ptr *uint8, val uint8)
283 TEXT ·Or8(SB), NOSPLIT, $0-9
284 MOV ptr+0(FP), A0
285 MOVBU val+8(FP), A1
286 AND $3, A0, A2
287 AND $-4, A0
288 SLL $3, A2
289 SLL A2, A1
290 AMOORW A1, (A0), ZERO
291 RET
292
293 // func And(ptr *uint32, val uint32)
294 TEXT ·And(SB), NOSPLIT, $0-12
295 MOV ptr+0(FP), A0
296 MOVW val+8(FP), A1
297 AMOANDW A1, (A0), ZERO
298 RET
299
300 // func Or(ptr *uint32, val uint32)
301 TEXT ·Or(SB), NOSPLIT, $0-12
302 MOV ptr+0(FP), A0
303 MOVW val+8(FP), A1
304 AMOORW A1, (A0), ZERO
305 RET
306
307 // func Or32(ptr *uint32, val uint32) uint32
308 TEXT ·Or32(SB), NOSPLIT, $0-20
309 MOV ptr+0(FP), A0
310 MOVW val+8(FP), A1
311 AMOORW A1, (A0), A2
312 MOVW A2, ret+16(FP)
313 RET
314
315 // func And32(ptr *uint32, val uint32) uint32
316 TEXT ·And32(SB), NOSPLIT, $0-20
317 MOV ptr+0(FP), A0
318 MOVW val+8(FP), A1
319 AMOANDW A1, (A0), A2
320 MOVW A2, ret+16(FP)
321 RET
322
323 // func Or64(ptr *uint64, val uint64) uint64
324 TEXT ·Or64(SB), NOSPLIT, $0-24
325 MOV ptr+0(FP), A0
326 MOV val+8(FP), A1
327 AMOORD A1, (A0), A2
328 MOV A2, ret+16(FP)
329 RET
330
331 // func And64(ptr *uint64, val uint64) uint64
332 TEXT ·And64(SB), NOSPLIT, $0-24
333 MOV ptr+0(FP), A0
334 MOV val+8(FP), A1
335 AMOANDD A1, (A0), A2
336 MOV A2, ret+16(FP)
337 RET
338
339 // func Anduintptr(ptr *uintptr, val uintptr) uintptr
340 TEXT ·Anduintptr(SB), NOSPLIT, $0-24
341 JMP ·And64(SB)
342
343 // func Oruintptr(ptr *uintptr, val uintptr) uintptr
344 TEXT ·Oruintptr(SB), NOSPLIT, $0-24
345 JMP ·Or64(SB)
346
View as plain text