github.com/primecitizens/pcz/std@v0.2.1/core/atomic/atomic_arm.s (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright 2023 The Prime Citizens
     3  //
     4  // Copyright 2015 The Go Authors. All rights reserved.
     5  // Use of this source code is governed by a BSD-style
     6  // license that can be found in the LICENSE file.
     7  
     8  //go:build arm
     9  
    10  #include "textflag.h"
    11  #include "funcdata.h"
    12  
    13  // armPublicationBarrier is a native store/store barrier for ARMv7+.
    14  // On earlier ARM revisions, armPublicationBarrier is a no-op.
    15  // This will not work on SMP ARMv6 machines, if any are in use.
    16  // To implement publicationBarrier in sys_$GOOS_arm.s using the native
    17  // instructions, use:
    18  //
    19  //	TEXT ·PublicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
    20  //		B runtime·armPublicationBarrier(SB)
    21  //
    22  TEXT ·PublicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
    23  	MOVB runtime·goarm(SB), R11
    24  	CMP $7, R11
    25  	BLT 2(PC)
    26  	DMB MB_ST
    27  	RET
    28  
    29  // bool armcas(int32 *val, int32 old, int32 new)
    30  //
    31  // To implement ·cas in sys_$GOOS_arm.s
    32  // using the native instructions, use:
    33  //
    34  //	TEXT ·cas(SB),NOSPLIT,$0
    35  //		B ·armcas(SB)
    36  //
    37  TEXT ·armcas(SB),NOSPLIT,$0-13
    38  	MOVW ptr+0(FP), R1
    39  	MOVW old+4(FP), R2
    40  	MOVW new+8(FP), R3
    41  casl:
    42  	LDREX (R1), R0
    43  	CMP R0, R2
    44  	BNE casfail
    45  
    46  	MOVB runtime·goarm(SB), R8
    47  	CMP $7, R8
    48  	BLT 2(PC)
    49  	DMB MB_ISHST
    50  
    51  	STREX R3, (R1), R0
    52  	CMP $0, R0
    53  	BNE casl
    54  	MOVW $1, R0
    55  
    56  	CMP $7, R8
    57  	BLT 2(PC)
    58  	DMB MB_ISH
    59  
    60  	MOVB R0, ret+12(FP)
    61  	RET
    62  casfail:
    63  	MOVW $0, R0
    64  	MOVB R0, ret+12(FP)
    65  	RET
    66  
    67  // 64-bit atomics
    68  // The native ARM implementations use LDREXD/STREXD, which are
    69  // available on ARMv6k or later. We use them only on ARMv7.
    70  // On older ARM, we use Go implementations which simulate 64-bit
    71  // atomics with locks.
    72  TEXT armCas64<>(SB),NOSPLIT,$0-21
    73  	// addr is already in R1
    74  	MOVW old_lo+4(FP), R2
    75  	MOVW old_hi+8(FP), R3
    76  	MOVW new_lo+12(FP), R4
    77  	MOVW new_hi+16(FP), R5
    78  cas64loop:
    79  	LDREXD (R1), R6 // loads R6 and R7
    80  	CMP R2, R6
    81  	BNE cas64fail
    82  	CMP R3, R7
    83  	BNE cas64fail
    84  
    85  	DMB MB_ISHST
    86  
    87  	STREXD R4, (R1), R0 // stores R4 and R5
    88  	CMP $0, R0
    89  	BNE cas64loop
    90  	MOVW $1, R0
    91  
    92  	DMB MB_ISH
    93  
    94  	MOVBU R0, swapped+20(FP)
    95  	RET
    96  cas64fail:
    97  	MOVW $0, R0
    98  	MOVBU R0, swapped+20(FP)
    99  	RET
   100  
   101  TEXT armAdd64<>(SB),NOSPLIT,$0-20
   102  	// addr is already in R1
   103  	MOVW delta_lo+4(FP), R2
   104  	MOVW delta_hi+8(FP), R3
   105  
   106  add64loop:
   107  	LDREXD (R1), R4 // loads R4 and R5
   108  	ADD.S R2, R4
   109  	ADC R3, R5
   110  
   111  	DMB MB_ISHST
   112  
   113  	STREXD R4, (R1), R0 // stores R4 and R5
   114  	CMP $0, R0
   115  	BNE add64loop
   116  
   117  	DMB MB_ISH
   118  
   119  	MOVW R4, new_lo+12(FP)
   120  	MOVW R5, new_hi+16(FP)
   121  	RET
   122  
   123  TEXT armSwap64<>(SB),NOSPLIT,$0-20
   124  	// addr is already in R1
   125  	MOVW new_lo+4(FP), R2
   126  	MOVW new_hi+8(FP), R3
   127  
   128  swap64loop:
   129  	LDREXD (R1), R4 // loads R4 and R5
   130  
   131  	DMB MB_ISHST
   132  
   133  	STREXD R2, (R1), R0 // stores R2 and R3
   134  	CMP $0, R0
   135  	BNE swap64loop
   136  
   137  	DMB MB_ISH
   138  
   139  	MOVW R4, old_lo+12(FP)
   140  	MOVW R5, old_hi+16(FP)
   141  	RET
   142  
   143  TEXT armLoad64<>(SB),NOSPLIT,$0-12
   144  	// addr is already in R1
   145  
   146  	LDREXD (R1), R2 // loads R2 and R3
   147  	DMB MB_ISH
   148  
   149  	MOVW R2, val_lo+4(FP)
   150  	MOVW R3, val_hi+8(FP)
   151  	RET
   152  
   153  TEXT armStore64<>(SB),NOSPLIT,$0-12
   154  	// addr is already in R1
   155  	MOVW val_lo+4(FP), R2
   156  	MOVW val_hi+8(FP), R3
   157  
   158  store64loop:
   159  	LDREXD (R1), R4 // loads R4 and R5
   160  
   161  	DMB MB_ISHST
   162  
   163  	STREXD R2, (R1), R0 // stores R2 and R3
   164  	CMP $0, R0
   165  	BNE store64loop
   166  
   167  	DMB MB_ISH
   168  	RET
   169  
   170  // The following functions all panic if their address argument isn't
   171  // 8-byte aligned. Since we're calling back into Go code to do this,
   172  // we have to cooperate with stack unwinding. In the normal case, the
   173  // functions tail-call into the appropriate implementation, which
   174  // means they must not open a frame. Hence, when they go down the
   175  // panic path, at that point they push the LR to create a real frame
   176  // (they don't need to pop it because panic won't return; however, we
   177  // do need to set the SP delta back).
   178  
   179  // Check if R1 is 8-byte aligned, panic if not.
   180  // Clobbers R2.
   181  #define CHECK_ALIGN \
   182  	AND.S $7, R1, R2 \
   183  	BEQ 	4(PC) \
   184  	MOVW.W R14, -4(R13) /* prepare a real frame */ \
   185  	BL ·panicUnaligned(SB) \
   186  	ADD $4, R13 /* compensate SP delta */
   187  
   188  //
   189  // Store
   190  //
   191  
   192  TEXT ·Store64(SB),NOSPLIT,$-4-12
   193  	NO_LOCAL_POINTERS
   194  	MOVW addr+0(FP), R1
   195  	CHECK_ALIGN
   196  
   197  	MOVB runtime·goarm(SB), R11
   198  	CMP $7, R11
   199  	BLT 2(PC)
   200  	JMP armStore64<>(SB)
   201  	JMP ·goStore64(SB)
   202  
   203  TEXT ·StoreUintptr(SB),NOSPLIT,$0-8
   204  	B ·Store(SB)
   205  
   206  TEXT ·StorePointer(SB),NOSPLIT,$0-8
   207  	B ·Store(SB)
   208  
   209  TEXT ·StoreInt32(SB),NOSPLIT,$0-8
   210  	B ·Store(SB)
   211  
   212  TEXT ·StoreInt64(SB),NOSPLIT,$0-12
   213  	B ·Store64(SB)
   214  
   215  //
   216  // StoreRel
   217  //
   218  
   219  TEXT ·StoreRel32(SB),NOSPLIT,$0-8
   220  	B ·Store(SB)
   221  
   222  TEXT ·StoreRelUintptr(SB),NOSPLIT,$0-8
   223  	B ·Store(SB)
   224  
   225  //
   226  // Load
   227  //
   228  
   229  TEXT ·Load64(SB),NOSPLIT,$-4-12
   230  	NO_LOCAL_POINTERS
   231  	MOVW addr+0(FP), R1
   232  	CHECK_ALIGN
   233  
   234  	MOVB runtime·goarm(SB), R11
   235  	CMP $7, R11
   236  	BLT 2(PC)
   237  	JMP armLoad64<>(SB)
   238  	JMP ·goLoad64(SB)
   239  
   240  TEXT ·LoadUintptr(SB),NOSPLIT,$0-8
   241  	B ·Load32(SB)
   242  
   243  TEXT ·LoadPointer(SB),NOSPLIT|NOFRAME,$0-8
   244  	B ·Load32(SB)
   245  
   246  TEXT ·LoadUint(SB),NOSPLIT,$0-8
   247  	B ·Load32(SB)
   248  
   249  TEXT ·LoadInt32(SB),NOSPLIT,$0-8
   250  	B ·Load32(SB)
   251  
   252  TEXT ·LoadInt64(SB),NOSPLIT,$-4-12
   253  	B ·Load64(SB)
   254  
   255  //
   256  // LoadAcq
   257  //
   258  
   259  TEXT ·LoadAcq32(SB),NOSPLIT|NOFRAME,$0-8
   260  	B ·Load32(SB)
   261  
   262  TEXT ·LoadAcqUintptr(SB),NOSPLIT|NOFRAME,$0-8
   263  	B 	·Load32(SB)
   264  
   265  //
   266  // bitwise
   267  //
   268  
   269  //
   270  // Swap
   271  //
   272  
   273  TEXT ·Swap64(SB),NOSPLIT,$-4-20
   274  	NO_LOCAL_POINTERS
   275  	MOVW addr+0(FP), R1
   276  	CHECK_ALIGN
   277  
   278  	MOVB runtime·goarm(SB), R11
   279  	CMP $7, R11
   280  	BLT 2(PC)
   281  	JMP armSwap64<>(SB)
   282  	JMP ·goSwap64(SB)
   283  
   284  TEXT ·SwapInt32(SB),NOSPLIT,$0-12
   285  	B ·Swap32(SB)
   286  
   287  TEXT ·SwapInt64(SB),NOSPLIT,$-4-20
   288  	B ·Swap64(SB)
   289  
   290  //
   291  // Add
   292  //
   293  
   294  TEXT ·Add64(SB),NOSPLIT,$-4-20
   295  	NO_LOCAL_POINTERS
   296  	MOVW addr+0(FP), R1
   297  	CHECK_ALIGN
   298  
   299  	MOVB runtime·goarm(SB), R11
   300  	CMP $7, R11
   301  	BLT 2(PC)
   302  	JMP armAdd64<>(SB)
   303  	JMP ·goAdd64(SB)
   304  
   305  TEXT ·AddUintptr(SB),NOSPLIT,$0-12
   306  	B ·Add32(SB)
   307  
   308  TEXT ·AddInt32(SB),NOSPLIT,$0-12
   309  	B ·Add32(SB)
   310  
   311  TEXT ·AddInt64(SB),NOSPLIT,$-4-20
   312  	B ·Add64(SB)
   313  
   314  //
   315  // Compare and swap
   316  //
   317  
   318  TEXT ·Cas64(SB),NOSPLIT,$-4-21
   319  	NO_LOCAL_POINTERS
   320  	MOVW addr+0(FP), R1
   321  	CHECK_ALIGN
   322  
   323  	MOVB runtime·goarm(SB), R11
   324  	CMP $7, R11
   325  	BLT 2(PC)
   326  	JMP armCas64<>(SB)
   327  	JMP ·goCas64(SB)
   328  
   329  TEXT ·CasInt32(SB),NOSPLIT,$0-13
   330  	B ·Cas(SB)
   331  
   332  TEXT ·CasInt64(SB),NOSPLIT,$-4-21
   333  	B ·Cas64(SB)
   334  
   335  TEXT ·CasUintptr(SB),NOSPLIT,$0-13
   336  	B ·Cas(SB)
   337  
   338  TEXT ·CasUnsafePointer(SB),NOSPLIT,$0-13
   339  	B ·Cas(SB)
   340  
   341  TEXT ·CasRel32(SB),NOSPLIT,$0-13
   342  	B ·Cas(SB)