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