github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/src/sync/atomic/asm_arm.s (about)

     1  // Copyright 2011 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  // +build !race
     6  
     7  #include "textflag.h"
     8  
     9  // ARM atomic operations, for use by asm_$(GOOS)_arm.s.
    10  
    11  #define DMB_ISHST_7 \
    12  	MOVB	runtime·goarm(SB), R11; \
    13  	CMP	$7, R11; \
    14  	BLT	2(PC); \
    15  	WORD	$0xf57ff05a	// dmb ishst
    16  
    17  #define DMB_ISH_7 \
    18  	MOVB	runtime·goarm(SB), R11; \
    19  	CMP	$7, R11; \
    20  	BLT	2(PC); \
    21  	WORD	$0xf57ff05b	// dmb ish
    22  
    23  TEXT ·armCompareAndSwapUint32(SB),NOSPLIT,$0-13
    24  	MOVW	addr+0(FP), R1
    25  	MOVW	old+4(FP), R2
    26  	MOVW	new+8(FP), R3
    27  casloop:
    28  	// LDREX and STREX were introduced in ARMv6.
    29  	LDREX	(R1), R0
    30  	CMP	R0, R2
    31  	BNE	casfail
    32  	DMB_ISHST_7
    33  	STREX	R3, (R1), R0
    34  	CMP	$0, R0
    35  	BNE	casloop
    36  	MOVW	$1, R0
    37  	DMB_ISH_7
    38  	MOVBU	R0, ret+12(FP)
    39  	RET
    40  casfail:
    41  	MOVW	$0, R0
    42  	MOVBU	R0, ret+12(FP)
    43  	RET
    44  
    45  TEXT ·armCompareAndSwapUint64(SB),NOSPLIT,$0-21
    46  	BL	fastCheck64<>(SB)
    47  	MOVW	addr+0(FP), R1
    48  	// make unaligned atomic access panic
    49  	AND.S	$7, R1, R2
    50  	BEQ 	2(PC)
    51  	MOVW	R2, (R2)
    52  	MOVW	oldlo+4(FP), R2
    53  	MOVW	oldhi+8(FP), R3
    54  	MOVW	newlo+12(FP), R4
    55  	MOVW	newhi+16(FP), R5
    56  cas64loop:
    57  	// LDREXD and STREXD were introduced in ARMv6k.
    58  	LDREXD	(R1), R6  // loads R6 and R7
    59  	CMP	R2, R6
    60  	BNE	cas64fail
    61  	CMP	R3, R7
    62  	BNE	cas64fail
    63  	DMB_ISHST_7
    64  	STREXD	R4, (R1), R0	// stores R4 and R5
    65  	CMP	$0, R0
    66  	BNE	cas64loop
    67  	MOVW	$1, R0
    68  	DMB_ISH_7
    69  	MOVBU	R0, ret+20(FP)
    70  	RET
    71  cas64fail:
    72  	MOVW	$0, R0
    73  	MOVBU	R0, ret+20(FP)
    74  	RET
    75  
    76  TEXT ·armAddUint32(SB),NOSPLIT,$0-12
    77  	MOVW	addr+0(FP), R1
    78  	MOVW	delta+4(FP), R2
    79  addloop:
    80  	// LDREX and STREX were introduced in ARMv6.
    81  	LDREX	(R1), R3
    82  	ADD	R2, R3
    83  	DMB_ISHST_7
    84  	STREX	R3, (R1), R0
    85  	CMP	$0, R0
    86  	BNE	addloop
    87  	DMB_ISH_7
    88  	MOVW	R3, ret+8(FP)
    89  	RET
    90  
    91  TEXT ·armAddUint64(SB),NOSPLIT,$0-20
    92  	BL	fastCheck64<>(SB)
    93  	MOVW	addr+0(FP), R1
    94  	// make unaligned atomic access panic
    95  	AND.S	$7, R1, R2
    96  	BEQ 	2(PC)
    97  	MOVW	R2, (R2)
    98  	MOVW	deltalo+4(FP), R2
    99  	MOVW	deltahi+8(FP), R3
   100  add64loop:
   101  	// LDREXD and STREXD were introduced in ARMv6k.
   102  	LDREXD	(R1), R4	// loads R4 and R5
   103  	ADD.S	R2, R4
   104  	ADC	R3, R5
   105  	DMB_ISHST_7
   106  	STREXD	R4, (R1), R0	// stores R4 and R5
   107  	CMP	$0, R0
   108  	BNE	add64loop
   109  	DMB_ISH_7
   110  	MOVW	R4, retlo+12(FP)
   111  	MOVW	R5, rethi+16(FP)
   112  	RET
   113  
   114  TEXT ·armSwapUint32(SB),NOSPLIT,$0-12
   115  	MOVW	addr+0(FP), R1
   116  	MOVW	new+4(FP), R2
   117  swaploop:
   118  	// LDREX and STREX were introduced in ARMv6.
   119  	LDREX	(R1), R3
   120  	DMB_ISHST_7
   121  	STREX	R2, (R1), R0
   122  	CMP	$0, R0
   123  	BNE	swaploop
   124  	DMB_ISH_7
   125  	MOVW	R3, old+8(FP)
   126  	RET
   127  
   128  TEXT ·armSwapUint64(SB),NOSPLIT,$0-20
   129  	BL	fastCheck64<>(SB)
   130  	MOVW	addr+0(FP), R1
   131  	// make unaligned atomic access panic
   132  	AND.S	$7, R1, R2
   133  	BEQ 	2(PC)
   134  	MOVW	R2, (R2)
   135  	MOVW	newlo+4(FP), R2
   136  	MOVW	newhi+8(FP), R3
   137  swap64loop:
   138  	// LDREXD and STREXD were introduced in ARMv6k.
   139  	LDREXD	(R1), R4	// loads R4 and R5
   140  	DMB_ISHST_7
   141  	STREXD	R2, (R1), R0	// stores R2 and R3
   142  	CMP	$0, R0
   143  	BNE	swap64loop
   144  	DMB_ISH_7
   145  	MOVW	R4, oldlo+12(FP)
   146  	MOVW	R5, oldhi+16(FP)
   147  	RET
   148  
   149  TEXT ·armLoadUint64(SB),NOSPLIT,$0-12
   150  	BL	fastCheck64<>(SB)
   151  	MOVW	addr+0(FP), R1
   152  	// make unaligned atomic access panic
   153  	AND.S	$7, R1, R2
   154  	BEQ 	2(PC)
   155  	MOVW	R2, (R2)
   156  load64loop:
   157  	LDREXD	(R1), R2	// loads R2 and R3
   158  	DMB_ISHST_7
   159  	STREXD	R2, (R1), R0	// stores R2 and R3
   160  	CMP	$0, R0
   161  	BNE	load64loop
   162  	DMB_ISH_7
   163  	MOVW	R2, vallo+4(FP)
   164  	MOVW	R3, valhi+8(FP)
   165  	RET
   166  
   167  TEXT ·armStoreUint64(SB),NOSPLIT,$0-12
   168  	BL	fastCheck64<>(SB)
   169  	MOVW	addr+0(FP), R1
   170  	// make unaligned atomic access panic
   171  	AND.S	$7, R1, R2
   172  	BEQ 	2(PC)
   173  	MOVW	R2, (R2)
   174  	MOVW	vallo+4(FP), R2
   175  	MOVW	valhi+8(FP), R3
   176  store64loop:
   177  	LDREXD	(R1), R4	// loads R4 and R5
   178  	DMB_ISHST_7
   179  	STREXD	R2, (R1), R0	// stores R2 and R3
   180  	CMP	$0, R0
   181  	BNE	store64loop
   182  	DMB_ISH_7
   183  	RET
   184  
   185  // Check for broken 64-bit LDREXD as found in QEMU.
   186  // LDREXD followed by immediate STREXD should succeed.
   187  // If it fails, try a few times just to be sure (maybe our thread got
   188  // rescheduled between the two instructions) and then panic.
   189  // A bug in some copies of QEMU makes STREXD never succeed,
   190  // which will make uses of the 64-bit atomic operations loop forever.
   191  // If things are working, set okLDREXD to avoid future checks.
   192  // https://bugs.launchpad.net/qemu/+bug/670883.
   193  TEXT	check64<>(SB),NOSPLIT,$16-0
   194  	MOVW	$10, R1
   195  	// 8-aligned stack address scratch space.
   196  	MOVW	$8(R13), R5
   197  	AND	$~7, R5
   198  loop:
   199  	LDREXD	(R5), R2
   200  	STREXD	R2, (R5), R0
   201  	CMP	$0, R0
   202  	BEQ	ok
   203  	SUB	$1, R1
   204  	CMP	$0, R1
   205  	BNE	loop
   206  	// Must be buggy QEMU.
   207  	BL	·panic64(SB)
   208  ok:
   209  	RET
   210  
   211  // Fast, cached version of check. No frame, just MOVW CMP RET after first time.
   212  TEXT	fastCheck64<>(SB),NOSPLIT,$-4
   213  	MOVW	ok64<>(SB), R0
   214  	CMP	$0, R0	// have we been here before?
   215  	RET.NE
   216  	B	slowCheck64<>(SB)
   217  
   218  TEXT slowCheck64<>(SB),NOSPLIT,$0-0
   219  	BL	check64<>(SB)
   220  	// Still here, must be okay.
   221  	MOVW	$1, R0
   222  	MOVW	R0, ok64<>(SB)
   223  	RET
   224  
   225  GLOBL ok64<>(SB), NOPTR, $4