github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/runtime/internal/atomic/atomic_arm.s (about) 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)