1 // Copyright 2015 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 #include "textflag.h"
6 #include "funcdata.h"
7
8 // bool armcas(int32 *val, int32 old, int32 new)
9 // Atomically:
10 // if(*val == old){
11 // *val = new;
12 // return 1;
13 // }else
14 // return 0;
15 //
16 // To implement ·cas in sys_$GOOS_arm.s
17 // using the native instructions, use:
18 //
19 // TEXT ·cas(SB),NOSPLIT,$0
20 // B ·armcas(SB)
21 //
22 TEXT ·armcas(SB),NOSPLIT,$0-13
23 MOVW ptr+0(FP), R1
24 MOVW old+4(FP), R2
25 MOVW new+8(FP), R3
26 casl:
27 LDREX (R1), R0
28 CMP R0, R2
29 BNE casfail
30
31 MOVB runtime·goarm(SB), R8
32 CMP $7, R8
33 BLT 2(PC)
34 DMB MB_ISHST
35
36 STREX R3, (R1), R0
37 CMP $0, R0
38 BNE casl
39 MOVW $1, R0
40
41 CMP $7, R8
42 BLT 2(PC)
43 DMB MB_ISH
44
45 MOVB R0, ret+12(FP)
46 RET
47 casfail:
48 MOVW $0, R0
49 MOVB R0, ret+12(FP)
50 RET
51
52 // stubs
53
54 TEXT ·Loadp(SB),NOSPLIT|NOFRAME,$0-8
55 B ·Load(SB)
56
57 TEXT ·LoadAcq(SB),NOSPLIT|NOFRAME,$0-8
58 B ·Load(SB)
59
60 TEXT ·LoadAcquintptr(SB),NOSPLIT|NOFRAME,$0-8
61 B ·Load(SB)
62
63 TEXT ·Casint32(SB),NOSPLIT,$0-13
64 B ·Cas(SB)
65
66 TEXT ·Casint64(SB),NOSPLIT,$-4-21
67 B ·Cas64(SB)
68
69 TEXT ·Casuintptr(SB),NOSPLIT,$0-13
70 B ·Cas(SB)
71
72 TEXT ·Casp1(SB),NOSPLIT,$0-13
73 B ·Cas(SB)
74
75 TEXT ·CasRel(SB),NOSPLIT,$0-13
76 B ·Cas(SB)
77
78 TEXT ·Loadint32(SB),NOSPLIT,$0-8
79 B ·Load(SB)
80
81 TEXT ·Loadint64(SB),NOSPLIT,$-4-12
82 B ·Load64(SB)
83
84 TEXT ·Loaduintptr(SB),NOSPLIT,$0-8
85 B ·Load(SB)
86
87 TEXT ·Loaduint(SB),NOSPLIT,$0-8
88 B ·Load(SB)
89
90 TEXT ·Storeint32(SB),NOSPLIT,$0-8
91 B ·Store(SB)
92
93 TEXT ·Storeint64(SB),NOSPLIT,$0-12
94 B ·Store64(SB)
95
96 TEXT ·Storeuintptr(SB),NOSPLIT,$0-8
97 B ·Store(SB)
98
99 TEXT ·StorepNoWB(SB),NOSPLIT,$0-8
100 B ·Store(SB)
101
102 TEXT ·StoreRel(SB),NOSPLIT,$0-8
103 B ·Store(SB)
104
105 TEXT ·StoreReluintptr(SB),NOSPLIT,$0-8
106 B ·Store(SB)
107
108 TEXT ·Xaddint32(SB),NOSPLIT,$0-12
109 B ·Xadd(SB)
110
111 TEXT ·Xaddint64(SB),NOSPLIT,$-4-20
112 B ·Xadd64(SB)
113
114 TEXT ·Xadduintptr(SB),NOSPLIT,$0-12
115 B ·Xadd(SB)
116
117 TEXT ·Xchgint32(SB),NOSPLIT,$0-12
118 B ·Xchg(SB)
119
120 TEXT ·Xchgint64(SB),NOSPLIT,$-4-20
121 B ·Xchg64(SB)
122
123 // 64-bit atomics
124 // The native ARM implementations use LDREXD/STREXD, which are
125 // available on ARMv6k or later. We use them only on ARMv7.
126 // On older ARM, we use Go implementations which simulate 64-bit
127 // atomics with locks.
128 TEXT armCas64<>(SB),NOSPLIT,$0-21
129 // addr is already in R1
130 MOVW old_lo+4(FP), R2
131 MOVW old_hi+8(FP), R3
132 MOVW new_lo+12(FP), R4
133 MOVW new_hi+16(FP), R5
134 cas64loop:
135 LDREXD (R1), R6 // loads R6 and R7
136 CMP R2, R6
137 BNE cas64fail
138 CMP R3, R7
139 BNE cas64fail
140
141 DMB MB_ISHST
142
143 STREXD R4, (R1), R0 // stores R4 and R5
144 CMP $0, R0
145 BNE cas64loop
146 MOVW $1, R0
147
148 DMB MB_ISH
149
150 MOVBU R0, swapped+20(FP)
151 RET
152 cas64fail:
153 MOVW $0, R0
154 MOVBU R0, swapped+20(FP)
155 RET
156
157 TEXT armXadd64<>(SB),NOSPLIT,$0-20
158 // addr is already in R1
159 MOVW delta_lo+4(FP), R2
160 MOVW delta_hi+8(FP), R3
161
162 add64loop:
163 LDREXD (R1), R4 // loads R4 and R5
164 ADD.S R2, R4
165 ADC R3, R5
166
167 DMB MB_ISHST
168
169 STREXD R4, (R1), R0 // stores R4 and R5
170 CMP $0, R0
171 BNE add64loop
172
173 DMB MB_ISH
174
175 MOVW R4, new_lo+12(FP)
176 MOVW R5, new_hi+16(FP)
177 RET
178
179 TEXT armXchg64<>(SB),NOSPLIT,$0-20
180 // addr is already in R1
181 MOVW new_lo+4(FP), R2
182 MOVW new_hi+8(FP), R3
183
184 swap64loop:
185 LDREXD (R1), R4 // loads R4 and R5
186
187 DMB MB_ISHST
188
189 STREXD R2, (R1), R0 // stores R2 and R3
190 CMP $0, R0
191 BNE swap64loop
192
193 DMB MB_ISH
194
195 MOVW R4, old_lo+12(FP)
196 MOVW R5, old_hi+16(FP)
197 RET
198
199 TEXT armLoad64<>(SB),NOSPLIT,$0-12
200 // addr is already in R1
201
202 LDREXD (R1), R2 // loads R2 and R3
203 DMB MB_ISH
204
205 MOVW R2, val_lo+4(FP)
206 MOVW R3, val_hi+8(FP)
207 RET
208
209 TEXT armStore64<>(SB),NOSPLIT,$0-12
210 // addr is already in R1
211 MOVW val_lo+4(FP), R2
212 MOVW val_hi+8(FP), R3
213
214 store64loop:
215 LDREXD (R1), R4 // loads R4 and R5
216
217 DMB MB_ISHST
218
219 STREXD R2, (R1), R0 // stores R2 and R3
220 CMP $0, R0
221 BNE store64loop
222
223 DMB MB_ISH
224 RET
225
226 // The following functions all panic if their address argument isn't
227 // 8-byte aligned. Since we're calling back into Go code to do this,
228 // we have to cooperate with stack unwinding. In the normal case, the
229 // functions tail-call into the appropriate implementation, which
230 // means they must not open a frame. Hence, when they go down the
231 // panic path, at that point they push the LR to create a real frame
232 // (they don't need to pop it because panic won't return; however, we
233 // do need to set the SP delta back).
234
235 // Check if R1 is 8-byte aligned, panic if not.
236 // Clobbers R2.
237 #define CHECK_ALIGN \
238 AND.S $7, R1, R2 \
239 BEQ 4(PC) \
240 MOVW.W R14, -4(R13) /* prepare a real frame */ \
241 BL ·panicUnaligned(SB) \
242 ADD $4, R13 /* compensate SP delta */
243
244 TEXT ·Cas64(SB),NOSPLIT,$-4-21
245 NO_LOCAL_POINTERS
246 MOVW addr+0(FP), R1
247 CHECK_ALIGN
248
249 MOVB runtime·goarm(SB), R11
250 CMP $7, R11
251 BLT 2(PC)
252 JMP armCas64<>(SB)
253 JMP ·goCas64(SB)
254
255 TEXT ·Xadd64(SB),NOSPLIT,$-4-20
256 NO_LOCAL_POINTERS
257 MOVW addr+0(FP), R1
258 CHECK_ALIGN
259
260 MOVB runtime·goarm(SB), R11
261 CMP $7, R11
262 BLT 2(PC)
263 JMP armXadd64<>(SB)
264 JMP ·goXadd64(SB)
265
266 TEXT ·Xchg64(SB),NOSPLIT,$-4-20
267 NO_LOCAL_POINTERS
268 MOVW addr+0(FP), R1
269 CHECK_ALIGN
270
271 MOVB runtime·goarm(SB), R11
272 CMP $7, R11
273 BLT 2(PC)
274 JMP armXchg64<>(SB)
275 JMP ·goXchg64(SB)
276
277 TEXT ·Load64(SB),NOSPLIT,$-4-12
278 NO_LOCAL_POINTERS
279 MOVW addr+0(FP), R1
280 CHECK_ALIGN
281
282 MOVB runtime·goarm(SB), R11
283 CMP $7, R11
284 BLT 2(PC)
285 JMP armLoad64<>(SB)
286 JMP ·goLoad64(SB)
287
288 TEXT ·Store64(SB),NOSPLIT,$-4-12
289 NO_LOCAL_POINTERS
290 MOVW addr+0(FP), R1
291 CHECK_ALIGN
292
293 MOVB runtime·goarm(SB), R11
294 CMP $7, R11
295 BLT 2(PC)
296 JMP armStore64<>(SB)
297 JMP ·goStore64(SB)
298
View as plain text