github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/sync/atomic/asm_riscv.s (about)

     1  // Copyright 2016 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 riscv
     6  
     7  // RISC-V's atomic operations have two bits, aq ("acquire") and rl ("release"),
     8  // which may be toggled on and off. Their precise semantics are defined in
     9  // section 6.3 of the specification, but the basic idea is as follows:
    10  //
    11  //   - If neither aq nor rl is set, the CPU may reorder the atomic arbitrarily.
    12  //     It guarantees only that it will execute atomically.
    13  //
    14  //   - If aq is set, the CPU may move the instruction backward, but not forward.
    15  //
    16  //   - If rl is set, the CPU may move the instruction forward, but not backward.
    17  //
    18  //   - If both are set, the CPU may not reorder the instruction at all.
    19  //
    20  // These four modes correspond to other well-known memory models on other CPUs.
    21  // On ARM, aq corresponds to a dmb ishst, aq+rl corresponds to a dmb ish. On
    22  // Intel, aq corresponds to an lfence, rl to an sfence, and aq+rl to an mfence
    23  // (or a lock prefix).
    24  //
    25  // Go's memory model requires that
    26  //   - if a read happens after a write, the read must observe the write, and
    27  //     that
    28  //   - if a read happens concurrently with a write, the read may observe the
    29  //     write.
    30  // aq is sufficient to guarantee this, so that's what we use here. (This jibes
    31  // with ARM, which uses dmb ishst.)
    32  
    33  #include "textflag.h"
    34  
    35  TEXT ·SwapInt32(SB),NOSPLIT,$0-20
    36  	JMP	·SwapUint32(SB)
    37  
    38  TEXT ·SwapInt64(SB),NOSPLIT,$0-24
    39  	JMP	·SwapUint64(SB)
    40  
    41  TEXT ·SwapUint32(SB),NOSPLIT,$0-20
    42  	MOV	addr+0(FP), A0
    43  	MOVW	new+8(FP), A1
    44  	WORD	$0x0cb525af	// amoswap.w.aq a1,a1,(a0)
    45  	MOVW	A1, old+16(FP)
    46  	RET
    47  
    48  TEXT ·SwapUint64(SB),NOSPLIT,$0-24
    49  	MOV	addr+0(FP), A0
    50  	MOV	new+8(FP), A1
    51  	WORD	$0x0cb535af	// amoswap.d.aq a1,a1,(a0)
    52  	MOV	A1, old+16(FP)
    53  	RET
    54  
    55  TEXT ·SwapUintptr(SB),NOSPLIT,$0-24
    56  	JMP	·SwapUint64(SB)
    57  
    58  TEXT ·CompareAndSwapInt32(SB),NOSPLIT,$0-17
    59  	JMP	·CompareAndSwapUint32(SB)
    60  
    61  TEXT ·CompareAndSwapInt64(SB),NOSPLIT,$0-25
    62  	JMP	·CompareAndSwapUint64(SB)
    63  
    64  TEXT ·CompareAndSwapUint32(SB),NOSPLIT,$0-17
    65  	MOV	addr+0(FP), A0
    66  	MOVW	old+8(FP), A1
    67  	MOVW	new+12(FP), A2
    68  cas:
    69  	WORD	$0x140522af	// lr.w.aq t0,(a0)
    70  	BNE	T0, A1, fail
    71  	WORD	$0x1cc5252f	// sc.w.aq a0,a2,(a0)
    72  	// a0 = 0 iff the sc succeeded. Convert that to a boolean.
    73  	SLTIU	$1, A0, A0
    74  	MOV	A0, swapped+16(FP)
    75  	RET
    76  fail:
    77  	MOV	$0, A0
    78  	MOV	A0, swapped+16(FP)
    79  	RET
    80  
    81  TEXT ·CompareAndSwapUint64(SB),NOSPLIT,$0-25
    82  	MOV	addr+0(FP), A0
    83  	MOV	old+8(FP), A1
    84  	MOV	new+16(FP), A2
    85  cas:
    86  	WORD	$0x140532af	// lr.d.aq t0,(a0)
    87  	BNE	T0, A1, fail
    88  	WORD	$0x1cc5352f	// sc.d.aq a0,a2,(a0)
    89  	// a0 = 0 iff the sc succeeded, a0 = 0. Convert that to a boolean.
    90  	SLTIU	$1, A0, A0
    91  	MOV	A0, swapped+24(FP)
    92  	RET
    93  fail:
    94  	MOV	$0, A0
    95  	MOV	A0, swapped+24(FP)
    96  	RET
    97  
    98  TEXT ·CompareAndSwapUintptr(SB),NOSPLIT,$0-25
    99  	JMP	·CompareAndSwapUint64(SB)
   100  
   101  TEXT ·AddInt32(SB),NOSPLIT,$0-20
   102  	JMP	·AddUint32(SB)
   103  
   104  TEXT ·AddUint32(SB),NOSPLIT,$0-20
   105  	MOV	addr+0(FP), A0
   106  	MOVW	delta+8(FP), A1
   107  	WORD	$0x04b5252f	// amoadd.w.aq a0,a1,(a0)
   108  	ADD	A0, A1
   109  	MOVW	A1, new+16(FP)
   110  	RET
   111  
   112  TEXT ·AddInt64(SB),NOSPLIT,$0-24
   113  	JMP	·AddUint64(SB)
   114  
   115  TEXT ·AddUint64(SB),NOSPLIT,$0-24
   116  	MOV	addr+0(FP), A0
   117  	MOV	delta+8(FP), A1
   118  	WORD	$0x04b5352f	// amoadd.d.aq a0,a1,(a0)
   119  	ADD	A0, A1
   120  	MOV	A1, new+16(FP)
   121  	RET
   122  
   123  TEXT ·AddUintptr(SB),NOSPLIT,$0-24
   124  	JMP	·AddUint64(SB)
   125  
   126  TEXT ·LoadInt32(SB),NOSPLIT,$0-12
   127  	JMP	·LoadUint32(SB)
   128  
   129  TEXT ·LoadInt64(SB),NOSPLIT,$0-16
   130  	JMP	·LoadUint64(SB)
   131  
   132  TEXT ·LoadUint32(SB),NOSPLIT,$0-12
   133  	MOV	addr+0(FP), A0
   134  	// Since addr is aligned (see comments in doc.go), this load is atomic
   135  	// automatically.
   136  	MOVW	(A0), A0
   137  	MOVW	A0, val+8(FP)
   138  	RET
   139  
   140  TEXT ·LoadUint64(SB),NOSPLIT,$0-16
   141  	MOV	addr+0(FP), A0
   142  	// Since addr is aligned (see comments in doc.go), this load is atomic
   143  	// automatically.
   144  	MOV	(A0), A0
   145  	MOV	A0, val+8(FP)
   146  	RET
   147  
   148  TEXT ·LoadUintptr(SB),NOSPLIT,$0-16
   149  	JMP	·LoadUint64(SB)
   150  
   151  TEXT ·LoadPointer(SB),NOSPLIT,$0-16
   152  	JMP	·LoadUint64(SB)
   153  
   154  TEXT ·StoreInt32(SB),NOSPLIT,$0-12
   155  	JMP	·StoreUint32(SB)
   156  
   157  TEXT ·StoreInt64(SB),NOSPLIT,$0-16
   158  	JMP	·StoreUint64(SB)
   159  
   160  TEXT ·StoreUint32(SB),NOSPLIT,$0-12
   161  	MOV	addr+0(FP), A0
   162  	MOVW	val+8(FP), A1
   163  	// Since addr is aligned (see comments in doc.go), this store is atomic
   164  	// automatically.
   165  	MOVW	A1, (A0)
   166  	RET
   167  
   168  TEXT ·StoreUint64(SB),NOSPLIT,$0-16
   169  	MOV	addr+0(FP), A0
   170  	MOV	val+8(FP), A1
   171  	// Since addr is aligned (see comments in doc.go), this store is atomic
   172  	// automatically.
   173  	MOV	A1, (A0)
   174  	RET
   175  
   176  TEXT ·StoreUintptr(SB),NOSPLIT,$0-16
   177  	JMP	·StoreUint64(SB)