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)