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 7 // Use kernel version instead of native armcas in asm_arm.s. 8 // See ../../../sync/atomic/asm_linux_arm.s for details. 9 TEXT cas<>(SB),NOSPLIT,$0 10 MOVW $0xffff0fc0, R15 // R15 is hardware PC. 11 12 TEXT runtimeinternalatomicCas(SB),NOSPLIT,$0 13 MOVW ptr+0(FP), R2 14 MOVW old+4(FP), R0 15 loop: 16 MOVW new+8(FP), R1 17 BL cas<>(SB) 18 BCC check 19 MOVW $1, R0 20 MOVB R0, ret+12(FP) 21 RET 22 check: 23 // Kernel lies; double-check. 24 MOVW ptr+0(FP), R2 25 MOVW old+4(FP), R0 26 MOVW 0(R2), R3 27 CMP R0, R3 28 BEQ loop 29 MOVW $0, R0 30 MOVB R0, ret+12(FP) 31 RET 32 33 TEXT runtimeinternalatomicCasp1(SB),NOSPLIT,$0 34 B runtimeinternalatomicCas(SB) 35 36 // As for cas, memory barriers are complicated on ARM, but the kernel 37 // provides a user helper. ARMv5 does not support SMP and has no 38 // memory barrier instruction at all. ARMv6 added SMP support and has 39 // a memory barrier, but it requires writing to a coprocessor 40 // register. ARMv7 introduced the DMB instruction, but it's expensive 41 // even on single-core devices. The kernel helper takes care of all of 42 // this for us.