| // Copyright 2016 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| #include "textflag.h" |
| |
| // func Store(ptr *uint32, val uint32) |
| TEXT ·Store(SB), NOSPLIT, $0 |
| MOVD ptr+0(FP), R2 |
| MOVWZ val+8(FP), R3 |
| MOVW R3, 0(R2) |
| SYNC |
| RET |
| |
| // func Store8(ptr *uint8, val uint8) |
| TEXT ·Store8(SB), NOSPLIT, $0 |
| MOVD ptr+0(FP), R2 |
| MOVB val+8(FP), R3 |
| MOVB R3, 0(R2) |
| SYNC |
| RET |
| |
| // func Store64(ptr *uint64, val uint64) |
| TEXT ·Store64(SB), NOSPLIT, $0 |
| MOVD ptr+0(FP), R2 |
| MOVD val+8(FP), R3 |
| MOVD R3, 0(R2) |
| SYNC |
| RET |
| |
| // func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer) |
| TEXT ·StorepNoWB(SB), NOSPLIT, $0 |
| MOVD ptr+0(FP), R2 |
| MOVD val+8(FP), R3 |
| MOVD R3, 0(R2) |
| SYNC |
| RET |
| |
| // func Cas(ptr *uint32, old, new uint32) bool |
| // Atomically: |
| // if *ptr == old { |
| // *val = new |
| // return 1 |
| // } else { |
| // return 0 |
| // } |
| TEXT ·Cas(SB), NOSPLIT, $0-17 |
| MOVD ptr+0(FP), R3 |
| MOVWZ old+8(FP), R4 |
| MOVWZ new+12(FP), R5 |
| CS R4, R5, 0(R3) // if (R4 == 0(R3)) then 0(R3)= R5 |
| BNE cas_fail |
| MOVB $1, ret+16(FP) |
| RET |
| cas_fail: |
| MOVB $0, ret+16(FP) |
| RET |
| |
| // func Cas64(ptr *uint64, old, new uint64) bool |
| // Atomically: |
| // if *ptr == old { |
| // *ptr = new |
| // return 1 |
| // } else { |
| // return 0 |
| // } |
| TEXT ·Cas64(SB), NOSPLIT, $0-25 |
| MOVD ptr+0(FP), R3 |
| MOVD old+8(FP), R4 |
| MOVD new+16(FP), R5 |
| CSG R4, R5, 0(R3) // if (R4 == 0(R3)) then 0(R3)= R5 |
| BNE cas64_fail |
| MOVB $1, ret+24(FP) |
| RET |
| cas64_fail: |
| MOVB $0, ret+24(FP) |
| RET |
| |
| // func Casuintptr(ptr *uintptr, old, new uintptr) bool |
| TEXT ·Casuintptr(SB), NOSPLIT, $0-25 |
| BR ·Cas64(SB) |
| |
| // func CasRel(ptr *uint32, old, new uint32) bool |
| TEXT ·CasRel(SB), NOSPLIT, $0-17 |
| BR ·Cas(SB) |
| |
| // func Loaduintptr(ptr *uintptr) uintptr |
| TEXT ·Loaduintptr(SB), NOSPLIT, $0-16 |
| BR ·Load64(SB) |
| |
| // func Loaduint(ptr *uint) uint |
| TEXT ·Loaduint(SB), NOSPLIT, $0-16 |
| BR ·Load64(SB) |
| |
| // func Storeuintptr(ptr *uintptr, new uintptr) |
| TEXT ·Storeuintptr(SB), NOSPLIT, $0-16 |
| BR ·Store64(SB) |
| |
| // func Loadint64(ptr *int64) int64 |
| TEXT ·Loadint64(SB), NOSPLIT, $0-16 |
| BR ·Load64(SB) |
| |
| // func Xadduintptr(ptr *uintptr, delta uintptr) uintptr |
| TEXT ·Xadduintptr(SB), NOSPLIT, $0-24 |
| BR ·Xadd64(SB) |
| |
| // func Xaddint64(ptr *int64, delta int64) int64 |
| TEXT ·Xaddint64(SB), NOSPLIT, $0-24 |
| BR ·Xadd64(SB) |
| |
| // func Casp1(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool |
| // Atomically: |
| // if *ptr == old { |
| // *ptr = new |
| // return 1 |
| // } else { |
| // return 0 |
| // } |
| TEXT ·Casp1(SB), NOSPLIT, $0-25 |
| BR ·Cas64(SB) |
| |
| // func Xadd(ptr *uint32, delta int32) uint32 |
| // Atomically: |
| // *ptr += delta |
| // return *ptr |
| TEXT ·Xadd(SB), NOSPLIT, $0-20 |
| MOVD ptr+0(FP), R4 |
| MOVW delta+8(FP), R5 |
| MOVW (R4), R3 |
| repeat: |
| ADD R5, R3, R6 |
| CS R3, R6, (R4) // if R3==(R4) then (R4)=R6 else R3=(R4) |
| BNE repeat |
| MOVW R6, ret+16(FP) |
| RET |
| |
| // func Xadd64(ptr *uint64, delta int64) uint64 |
| TEXT ·Xadd64(SB), NOSPLIT, $0-24 |
| MOVD ptr+0(FP), R4 |
| MOVD delta+8(FP), R5 |
| MOVD (R4), R3 |
| repeat: |
| ADD R5, R3, R6 |
| CSG R3, R6, (R4) // if R3==(R4) then (R4)=R6 else R3=(R4) |
| BNE repeat |
| MOVD R6, ret+16(FP) |
| RET |
| |
| // func Xchg(ptr *uint32, new uint32) uint32 |
| TEXT ·Xchg(SB), NOSPLIT, $0-20 |
| MOVD ptr+0(FP), R4 |
| MOVW new+8(FP), R3 |
| MOVW (R4), R6 |
| repeat: |
| CS R6, R3, (R4) // if R6==(R4) then (R4)=R3 else R6=(R4) |
| BNE repeat |
| MOVW R6, ret+16(FP) |
| RET |
| |
| // func Xchg64(ptr *uint64, new uint64) uint64 |
| TEXT ·Xchg64(SB), NOSPLIT, $0-24 |
| MOVD ptr+0(FP), R4 |
| MOVD new+8(FP), R3 |
| MOVD (R4), R6 |
| repeat: |
| CSG R6, R3, (R4) // if R6==(R4) then (R4)=R3 else R6=(R4) |
| BNE repeat |
| MOVD R6, ret+16(FP) |
| RET |
| |
| // func Xchguintptr(ptr *uintptr, new uintptr) uintptr |
| TEXT ·Xchguintptr(SB), NOSPLIT, $0-24 |
| BR ·Xchg64(SB) |
| |
| // func Or8(addr *uint8, v uint8) |
| TEXT ·Or8(SB), NOSPLIT, $0-9 |
| MOVD ptr+0(FP), R3 |
| MOVBZ val+8(FP), R4 |
| // We don't have atomic operations that work on individual bytes so we |
| // need to align addr down to a word boundary and create a mask |
| // containing v to OR with the entire word atomically. |
| MOVD $(3<<3), R5 |
| RXSBG $59, $60, $3, R3, R5 // R5 = 24 - ((addr % 4) * 8) = ((addr & 3) << 3) ^ (3 << 3) |
| ANDW $~3, R3 // R3 = floor(addr, 4) = addr &^ 3 |
| SLW R5, R4 // R4 = uint32(v) << R5 |
| LAO R4, R6, 0(R3) // R6 = *R3; *R3 |= R4; (atomic) |
| RET |
| |
| // func And8(addr *uint8, v uint8) |
| TEXT ·And8(SB), NOSPLIT, $0-9 |
| MOVD ptr+0(FP), R3 |
| MOVBZ val+8(FP), R4 |
| // We don't have atomic operations that work on individual bytes so we |
| // need to align addr down to a word boundary and create a mask |
| // containing v to AND with the entire word atomically. |
| ORW $~0xff, R4 // R4 = uint32(v) | 0xffffff00 |
| MOVD $(3<<3), R5 |
| RXSBG $59, $60, $3, R3, R5 // R5 = 24 - ((addr % 4) * 8) = ((addr & 3) << 3) ^ (3 << 3) |
| ANDW $~3, R3 // R3 = floor(addr, 4) = addr &^ 3 |
| RLL R5, R4, R4 // R4 = rotl(R4, R5) |
| LAN R4, R6, 0(R3) // R6 = *R3; *R3 &= R4; (atomic) |
| RET |
| |
| // func Or(addr *uint32, v uint32) |
| TEXT ·Or(SB), NOSPLIT, $0-12 |
| MOVD ptr+0(FP), R3 |
| MOVW val+8(FP), R4 |
| LAO R4, R6, 0(R3) // R6 = *R3; *R3 |= R4; (atomic) |
| RET |
| |
| // func And(addr *uint32, v uint32) |
| TEXT ·And(SB), NOSPLIT, $0-12 |
| MOVD ptr+0(FP), R3 |
| MOVW val+8(FP), R4 |
| LAN R4, R6, 0(R3) // R6 = *R3; *R3 &= R4; (atomic) |
| RET |