github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/runtime/internal/atomic/asm_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 ·Casuintptr(SB),NOSPLIT,$0-13 64 B ·Cas(SB) 65 66 TEXT ·Casp1(SB),NOSPLIT,$0-13 67 B ·Cas(SB) 68 69 TEXT ·CasRel(SB),NOSPLIT,$0-13 70 B ·Cas(SB) 71 72 TEXT ·Loaduintptr(SB),NOSPLIT,$0-8 73 B ·Load(SB) 74 75 TEXT ·Loaduint(SB),NOSPLIT,$0-8 76 B ·Load(SB) 77 78 TEXT ·Storeuintptr(SB),NOSPLIT,$0-8 79 B ·Store(SB) 80 81 TEXT ·StorepNoWB(SB),NOSPLIT,$0-8 82 B ·Store(SB) 83 84 TEXT ·StoreRel(SB),NOSPLIT,$0-8 85 B ·Store(SB) 86 87 TEXT ·StoreReluintptr(SB),NOSPLIT,$0-8 88 B ·Store(SB) 89 90 TEXT ·Xadduintptr(SB),NOSPLIT,$0-12 91 B ·Xadd(SB) 92 93 TEXT ·Loadint64(SB),NOSPLIT,$0-12 94 B ·Load64(SB) 95 96 TEXT ·Xaddint64(SB),NOSPLIT,$0-20 97 B ·Xadd64(SB) 98 99 // 64-bit atomics 100 // The native ARM implementations use LDREXD/STREXD, which are 101 // available on ARMv6k or later. We use them only on ARMv7. 102 // On older ARM, we use Go implementations which simulate 64-bit 103 // atomics with locks. 104 105 TEXT armCas64<>(SB),NOSPLIT,$0-21 106 // addr is already in R1 107 MOVW old_lo+4(FP), R2 108 MOVW old_hi+8(FP), R3 109 MOVW new_lo+12(FP), R4 110 MOVW new_hi+16(FP), R5 111 cas64loop: 112 LDREXD (R1), R6 // loads R6 and R7 113 CMP R2, R6 114 BNE cas64fail 115 CMP R3, R7 116 BNE cas64fail 117 118 DMB MB_ISHST 119 120 STREXD R4, (R1), R0 // stores R4 and R5 121 CMP $0, R0 122 BNE cas64loop 123 MOVW $1, R0 124 125 DMB MB_ISH 126 127 MOVBU R0, swapped+20(FP) 128 RET 129 cas64fail: 130 MOVW $0, R0 131 MOVBU R0, swapped+20(FP) 132 RET 133 134 TEXT armXadd64<>(SB),NOSPLIT,$0-20 135 // addr is already in R1 136 MOVW delta_lo+4(FP), R2 137 MOVW delta_hi+8(FP), R3 138 139 add64loop: 140 LDREXD (R1), R4 // loads R4 and R5 141 ADD.S R2, R4 142 ADC R3, R5 143 144 DMB MB_ISHST 145 146 STREXD R4, (R1), R0 // stores R4 and R5 147 CMP $0, R0 148 BNE add64loop 149 150 DMB MB_ISH 151 152 MOVW R4, new_lo+12(FP) 153 MOVW R5, new_hi+16(FP) 154 RET 155 156 TEXT armXchg64<>(SB),NOSPLIT,$0-20 157 // addr is already in R1 158 MOVW new_lo+4(FP), R2 159 MOVW new_hi+8(FP), R3 160 161 swap64loop: 162 LDREXD (R1), R4 // loads R4 and R5 163 164 DMB MB_ISHST 165 166 STREXD R2, (R1), R0 // stores R2 and R3 167 CMP $0, R0 168 BNE swap64loop 169 170 DMB MB_ISH 171 172 MOVW R4, old_lo+12(FP) 173 MOVW R5, old_hi+16(FP) 174 RET 175 176 TEXT armLoad64<>(SB),NOSPLIT,$0-12 177 // addr is already in R1 178 179 LDREXD (R1), R2 // loads R2 and R3 180 DMB MB_ISH 181 182 MOVW R2, val_lo+4(FP) 183 MOVW R3, val_hi+8(FP) 184 RET 185 186 TEXT armStore64<>(SB),NOSPLIT,$0-12 187 // addr is already in R1 188 MOVW val_lo+4(FP), R2 189 MOVW val_hi+8(FP), R3 190 191 store64loop: 192 LDREXD (R1), R4 // loads R4 and R5 193 194 DMB MB_ISHST 195 196 STREXD R2, (R1), R0 // stores R2 and R3 197 CMP $0, R0 198 BNE store64loop 199 200 DMB MB_ISH 201 RET 202 203 // The following functions all panic if their address argument isn't 204 // 8-byte aligned. Since we're calling back into Go code to do this, 205 // we have to cooperate with stack unwinding. In the normal case, the 206 // functions tail-call into the appropriate implementation, which 207 // means they must not open a frame. Hence, when they go down the 208 // panic path, at that point they push the LR to create a real frame 209 // (they don't need to pop it because panic won't return). 210 211 TEXT ·Cas64(SB),NOSPLIT,$-4-21 212 NO_LOCAL_POINTERS 213 MOVW addr+0(FP), R1 214 // make unaligned atomic access panic 215 AND.S $7, R1, R2 216 BEQ 3(PC) 217 MOVW.W R14, -4(R13) // prepare a real frame 218 BL ·panicUnaligned(SB) 219 220 MOVB runtime·goarm(SB), R11 221 CMP $7, R11 222 BLT 2(PC) 223 JMP armCas64<>(SB) 224 JMP ·goCas64(SB) 225 226 TEXT ·Xadd64(SB),NOSPLIT,$-4-20 227 NO_LOCAL_POINTERS 228 MOVW addr+0(FP), R1 229 // make unaligned atomic access panic 230 AND.S $7, R1, R2 231 BEQ 3(PC) 232 MOVW.W R14, -4(R13) // prepare a real frame 233 BL ·panicUnaligned(SB) 234 235 MOVB runtime·goarm(SB), R11 236 CMP $7, R11 237 BLT 2(PC) 238 JMP armXadd64<>(SB) 239 JMP ·goXadd64(SB) 240 241 TEXT ·Xchg64(SB),NOSPLIT,$-4-20 242 NO_LOCAL_POINTERS 243 MOVW addr+0(FP), R1 244 // make unaligned atomic access panic 245 AND.S $7, R1, R2 246 BEQ 3(PC) 247 MOVW.W R14, -4(R13) // prepare a real frame 248 BL ·panicUnaligned(SB) 249 250 MOVB runtime·goarm(SB), R11 251 CMP $7, R11 252 BLT 2(PC) 253 JMP armXchg64<>(SB) 254 JMP ·goXchg64(SB) 255 256 TEXT ·Load64(SB),NOSPLIT,$-4-12 257 NO_LOCAL_POINTERS 258 MOVW addr+0(FP), R1 259 // make unaligned atomic access panic 260 AND.S $7, R1, R2 261 BEQ 3(PC) 262 MOVW.W R14, -4(R13) // prepare a real frame 263 BL ·panicUnaligned(SB) 264 265 MOVB runtime·goarm(SB), R11 266 CMP $7, R11 267 BLT 2(PC) 268 JMP armLoad64<>(SB) 269 JMP ·goLoad64(SB) 270 271 TEXT ·Store64(SB),NOSPLIT,$-4-12 272 NO_LOCAL_POINTERS 273 MOVW addr+0(FP), R1 274 // make unaligned atomic access panic 275 AND.S $7, R1, R2 276 BEQ 3(PC) 277 MOVW.W R14, -4(R13) // prepare a real frame 278 BL ·panicUnaligned(SB) 279 280 MOVB runtime·goarm(SB), R11 281 CMP $7, R11 282 BLT 2(PC) 283 JMP armStore64<>(SB) 284 JMP ·goStore64(SB)