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)