github.com/x04/go/src@v0.0.0-20200202162449-3d481ceb3525/runtime/internal/atomic/atomic_riscv64.s (about) 1 // Copyright 2014 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 // RISC-V's atomic operations have two bits, aq ("acquire") and rl ("release"), 6 // which may be toggled on and off. Their precise semantics are defined in 7 // section 6.3 of the specification, but the basic idea is as follows: 8 // 9 // - If neither aq nor rl is set, the CPU may reorder the atomic arbitrarily. 10 // It guarantees only that it will execute atomically. 11 // 12 // - If aq is set, the CPU may move the instruction backward, but not forward. 13 // 14 // - If rl is set, the CPU may move the instruction forward, but not backward. 15 // 16 // - If both are set, the CPU may not reorder the instruction at all. 17 // 18 // These four modes correspond to other well-known memory models on other CPUs. 19 // On ARM, aq corresponds to a dmb ishst, aq+rl corresponds to a dmb ish. On 20 // Intel, aq corresponds to an lfence, rl to an sfence, and aq+rl to an mfence 21 // (or a lock prefix). 22 // 23 // Go's memory model requires that 24 // - if a read happens after a write, the read must observe the write, and 25 // that 26 // - if a read happens concurrently with a write, the read may observe the 27 // write. 28 // aq is sufficient to guarantee this, so that's what we use here. (This jibes 29 // with ARM, which uses dmb ishst.) 30 31 #include "textflag.h" 32 33 #define AMOWSC(op,rd,rs1,rs2) WORD $0x0600202f+rd<<7+rs1<<15+rs2<<20+op<<27 34 #define AMODSC(op,rd,rs1,rs2) WORD $0x0600302f+rd<<7+rs1<<15+rs2<<20+op<<27 35 #define ADD_ 0 36 #define SWAP_ 1 37 #define LR_ 2 38 #define SC_ 3 39 #define OR_ 8 40 #define AND_ 12 41 #define FENCE WORD $0x0ff0000f 42 43 // Atomically: 44 // if(*val == *old){ 45 // *val = new; 46 // return 1; 47 // } else { 48 // return 0; 49 // } 50 51 TEXT ·Cas(SB), NOSPLIT, $0-17 52 MOV ptr+0(FP), A0 53 MOVW old+8(FP), A1 54 MOVW new+12(FP), A2 55 cas_again: 56 AMOWSC(LR_,13,10,0) // lr.w.aq a3,(a0) 57 BNE A3, A1, cas_fail 58 AMOWSC(SC_,14,10,12) // sc.w.aq a4,a2,(a0) 59 BNE A4, ZERO, cas_again 60 MOV $1, A0 61 MOVB A0, ret+16(FP) 62 RET 63 cas_fail: 64 MOV $0, A0 65 MOV A0, ret+16(FP) 66 RET 67 68 // func Cas64(ptr *uint64, old, new uint64) bool 69 TEXT ·Cas64(SB), NOSPLIT, $0-25 70 MOV ptr+0(FP), A0 71 MOV old+8(FP), A1 72 MOV new+16(FP), A2 73 cas_again: 74 AMODSC(LR_,13,10,0) // lr.d.aq a3,(a0) 75 BNE A3, A1, cas_fail 76 AMODSC(SC_,14,10,12) // sc.d.aq a4,a2,(a0) 77 BNE A4, ZERO, cas_again 78 MOV $1, A0 79 MOVB A0, ret+24(FP) 80 RET 81 cas_fail: 82 MOVB ZERO, ret+24(FP) 83 RET 84 85 // func Load(ptr *uint32) uint32 86 TEXT ·Load(SB),NOSPLIT|NOFRAME,$0-12 87 MOV ptr+0(FP), A0 88 AMOWSC(LR_,10,10,0) 89 MOVW A0, ret+8(FP) 90 RET 91 92 // func Load8(ptr *uint8) uint8 93 TEXT ·Load8(SB),NOSPLIT|NOFRAME,$0-9 94 MOV ptr+0(FP), A0 95 FENCE 96 MOVBU (A0), A1 97 FENCE 98 MOVB A1, ret+8(FP) 99 RET 100 101 // func Load64(ptr *uint64) uint64 102 TEXT ·Load64(SB),NOSPLIT|NOFRAME,$0-16 103 MOV ptr+0(FP), A0 104 AMODSC(LR_,10,10,0) 105 MOV A0, ret+8(FP) 106 RET 107 108 // func Store(ptr *uint32, val uint32) 109 TEXT ·Store(SB), NOSPLIT, $0-12 110 MOV ptr+0(FP), A0 111 MOVW val+8(FP), A1 112 AMOWSC(SWAP_,0,10,11) 113 RET 114 115 // func Store8(ptr *uint8, val uint8) 116 TEXT ·Store8(SB), NOSPLIT, $0-9 117 MOV ptr+0(FP), A0 118 MOVBU val+8(FP), A1 119 FENCE 120 MOVB A1, (A0) 121 FENCE 122 RET 123 124 // func Store64(ptr *uint64, val uint64) 125 TEXT ·Store64(SB), NOSPLIT, $0-16 126 MOV ptr+0(FP), A0 127 MOV val+8(FP), A1 128 AMODSC(SWAP_,0,10,11) 129 RET 130 131 TEXT ·Casp1(SB), NOSPLIT, $0-25 132 JMP ·Cas64(SB) 133 134 TEXT ·Casuintptr(SB),NOSPLIT,$0-25 135 JMP ·Cas64(SB) 136 137 TEXT ·CasRel(SB), NOSPLIT, $0-17 138 JMP ·Cas(SB) 139 140 TEXT ·Loaduintptr(SB),NOSPLIT,$0-16 141 JMP ·Load64(SB) 142 143 TEXT ·Storeuintptr(SB),NOSPLIT,$0-16 144 JMP ·Store64(SB) 145 146 TEXT ·Loaduint(SB),NOSPLIT,$0-16 147 JMP ·Loaduintptr(SB) 148 149 TEXT ·Loadint64(SB),NOSPLIT,$0-16 150 JMP ·Loaduintptr(SB) 151 152 TEXT ·Xaddint64(SB),NOSPLIT,$0-24 153 MOV ptr+0(FP), A0 154 MOV delta+8(FP), A1 155 WORD $0x04b5352f // amoadd.d.aq a0,a1,(a0) 156 ADD A0, A1, A0 157 MOVW A0, ret+16(FP) 158 RET 159 160 TEXT ·LoadAcq(SB),NOSPLIT|NOFRAME,$0-12 161 JMP ·Load(SB) 162 163 // func Loadp(ptr unsafe.Pointer) unsafe.Pointer 164 TEXT ·Loadp(SB),NOSPLIT,$0-16 165 JMP ·Load64(SB) 166 167 // func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer) 168 TEXT ·StorepNoWB(SB), NOSPLIT, $0-16 169 JMP ·Store64(SB) 170 171 TEXT ·StoreRel(SB), NOSPLIT, $0-12 172 JMP ·Store(SB) 173 174 // func Xchg(ptr *uint32, new uint32) uint32 175 TEXT ·Xchg(SB), NOSPLIT, $0-20 176 MOV ptr+0(FP), A0 177 MOVW new+8(FP), A1 178 AMOWSC(SWAP_,11,10,11) 179 MOVW A1, ret+16(FP) 180 RET 181 182 // func Xchg64(ptr *uint64, new uint64) uint64 183 TEXT ·Xchg64(SB), NOSPLIT, $0-24 184 MOV ptr+0(FP), A0 185 MOV new+8(FP), A1 186 AMODSC(SWAP_,11,10,11) 187 MOV A1, ret+16(FP) 188 RET 189 190 // Atomically: 191 // *val += delta; 192 // return *val; 193 194 // func Xadd(ptr *uint32, delta int32) uint32 195 TEXT ·Xadd(SB), NOSPLIT, $0-20 196 MOV ptr+0(FP), A0 197 MOVW delta+8(FP), A1 198 AMOWSC(ADD_,12,10,11) 199 ADD A2,A1,A0 200 MOVW A0, ret+16(FP) 201 RET 202 203 // func Xadd64(ptr *uint64, delta int64) uint64 204 TEXT ·Xadd64(SB), NOSPLIT, $0-24 205 MOV ptr+0(FP), A0 206 MOV delta+8(FP), A1 207 AMODSC(ADD_,12,10,11) 208 ADD A2,A1,A0 209 MOV A0, ret+16(FP) 210 RET 211 212 // func Xadduintptr(ptr *uintptr, delta uintptr) uintptr 213 TEXT ·Xadduintptr(SB), NOSPLIT, $0-24 214 JMP ·Xadd64(SB) 215 216 // func Xchguintptr(ptr *uintptr, new uintptr) uintptr 217 TEXT ·Xchguintptr(SB), NOSPLIT, $0-24 218 JMP ·Xchg64(SB) 219 220 // func And8(ptr *uint8, val uint8) 221 TEXT ·And8(SB), NOSPLIT, $0-9 222 MOV ptr+0(FP), A0 223 MOVBU val+8(FP), A1 224 AND $3, A0, A2 225 AND $-4, A0 226 SLL $3, A2 227 XOR $255, A1 228 SLL A2, A1 229 XOR $-1, A1 230 AMOWSC(AND_,0,10,11) 231 RET 232 233 // func Or8(ptr *uint8, val uint8) 234 TEXT ·Or8(SB), NOSPLIT, $0-9 235 MOV ptr+0(FP), A0 236 MOVBU val+8(FP), A1 237 AND $3, A0, A2 238 AND $-4, A0 239 SLL $3, A2 240 SLL A2, A1 241 AMOWSC(OR_,0,10,11) 242 RET