]> Cypherpunks repositories - gostls13.git/commitdiff
runtime/internal/atomic: add GOARCH=mips{,le} support
authorVladimir Stefanovic <vladimir.stefanovic@imgtec.com>
Tue, 18 Oct 2016 21:51:04 +0000 (23:51 +0200)
committerBrad Fitzpatrick <bradfitz@golang.org>
Thu, 3 Nov 2016 22:43:50 +0000 (22:43 +0000)
Change-Id: I99a48f719fd1a8178fc59787084a074e91c89ac6
Reviewed-on: https://go-review.googlesource.com/31489
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/runtime/internal/atomic/asm_mipsx.s [new file with mode: 0644]
src/runtime/internal/atomic/atomic_mipsx.go [new file with mode: 0644]
src/runtime/internal/atomic/atomic_mipsx.s [new file with mode: 0644]

diff --git a/src/runtime/internal/atomic/asm_mipsx.s b/src/runtime/internal/atomic/asm_mipsx.s
new file mode 100644 (file)
index 0000000..30550fd
--- /dev/null
@@ -0,0 +1,149 @@
+// 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.
+
+// +build mips mipsle
+
+#include "textflag.h"
+
+TEXT ·Cas(SB),NOSPLIT,$0-13
+       MOVW    ptr+0(FP), R1
+       MOVW    old+4(FP), R2
+       MOVW    new+8(FP), R5
+       SYNC
+try_cas:
+       MOVW    R5, R3
+       LL      (R1), R4        // R4 = *R1
+       BNE     R2, R4, cas_fail
+       SC      R3, (R1)        // *R1 = R3
+       BEQ     R3, try_cas
+       SYNC
+       MOVB    R3, ret+12(FP)
+       RET
+cas_fail:
+       MOVB    R0, ret+12(FP)
+       RET
+
+TEXT ·Store(SB),NOSPLIT,$0-8
+       MOVW    ptr+0(FP), R1
+       MOVW    val+4(FP), R2
+       SYNC
+       MOVW    R2, 0(R1)
+       SYNC
+       RET
+
+TEXT ·Load(SB),NOSPLIT,$0-8
+       MOVW    ptr+0(FP), R1
+       SYNC
+       MOVW    0(R1), R1
+       SYNC
+       MOVW    R1, ret+4(FP)
+       RET
+
+TEXT ·Xadd(SB),NOSPLIT,$0-12
+       MOVW    ptr+0(FP), R2
+       MOVW    delta+4(FP), R3
+       SYNC
+try_xadd:
+       LL      (R2), R1        // R1 = *R2
+       ADDU    R1, R3, R4
+       MOVW    R4, R1
+       SC      R4, (R2)        // *R2 = R4
+       BEQ     R4, try_xadd
+       SYNC
+       MOVW    R1, ret+8(FP)
+       RET
+
+TEXT ·Xchg(SB),NOSPLIT,$0-12
+       MOVW    ptr+0(FP), R2
+       MOVW    new+4(FP), R5
+       SYNC
+try_xchg:
+       MOVW    R5, R3
+       LL      (R2), R1        // R1 = *R2
+       SC      R3, (R2)        // *R2 = R3
+       BEQ     R3, try_xchg
+       SYNC
+       MOVW    R1, ret+8(FP)
+       RET
+
+TEXT ·Casuintptr(SB),NOSPLIT,$0-13
+       JMP     ·Cas(SB)
+
+TEXT ·Loaduintptr(SB),NOSPLIT,$0-8
+       JMP     ·Load(SB)
+
+TEXT ·Loaduint(SB),NOSPLIT,$0-8
+       JMP     ·Load(SB)
+
+TEXT ·Loadp(SB),NOSPLIT,$-0-8
+       JMP     ·Load(SB)
+
+TEXT ·Storeuintptr(SB),NOSPLIT,$0-8
+       JMP     ·Store(SB)
+
+TEXT ·Xadduintptr(SB),NOSPLIT,$0-12
+       JMP     ·Xadd(SB)
+
+TEXT ·Loadint64(SB),NOSPLIT,$0-12
+       JMP     ·Load64(SB)
+
+TEXT ·Xaddint64(SB),NOSPLIT,$0-20
+       JMP     ·Xadd64(SB)
+
+TEXT ·Casp1(SB),NOSPLIT,$0-13
+       JMP     ·Cas(SB)
+
+TEXT ·Xchguintptr(SB),NOSPLIT,$0-12
+       JMP     ·Xchg(SB)
+
+TEXT ·StorepNoWB(SB),NOSPLIT,$0-8
+       JMP     ·Store(SB)
+
+// void        Or8(byte volatile*, byte);
+TEXT ·Or8(SB),NOSPLIT,$0-5
+       MOVW    ptr+0(FP), R1
+       MOVBU   val+4(FP), R2
+       MOVW    $~3, R3 // Align ptr down to 4 bytes so we can use 32-bit load/store.
+       AND     R1, R3
+#ifdef GOARCH_mips
+       // Big endian.  ptr = ptr ^ 3
+       XOR     $3, R1
+#endif
+       AND     $3, R1, R4      // R4 = ((ptr & 3) * 8)
+       SLL     $3, R4
+       SLL     R4, R2, R2      // Shift val for aligned ptr. R2 = val << R4
+       SYNC
+try_or8:
+       LL      (R3), R4        // R4 = *R3
+       OR      R2, R4
+       SC      R4, (R3)        // *R3 = R4
+       BEQ     R4, try_or8
+       SYNC
+       RET
+
+// void        And8(byte volatile*, byte);
+TEXT ·And8(SB),NOSPLIT,$0-5
+       MOVW    ptr+0(FP), R1
+       MOVBU   val+4(FP), R2
+       MOVW    $~3, R3
+       AND     R1, R3
+#ifdef GOARCH_mips
+       // Big endian.  ptr = ptr ^ 3
+       XOR     $3, R1
+#endif
+       AND     $3, R1, R4      // R4 = ((ptr & 3) * 8)
+       SLL     $3, R4
+       MOVW    $0xFF, R5
+       SLL     R4, R2
+       SLL     R4, R5
+       NOR     R0, R5
+       OR      R5, R2  // Shift val for aligned ptr. R2 = val << R4 | ^(0xFF << R4)
+       SYNC
+try_and8:
+       LL      (R3), R4        // R4 = *R3
+       AND     R2, R4
+       SC      R4, (R3)        // *R3 = R4
+       BEQ     R4, try_and8
+       SYNC
+       RET
diff --git a/src/runtime/internal/atomic/atomic_mipsx.go b/src/runtime/internal/atomic/atomic_mipsx.go
new file mode 100644 (file)
index 0000000..20b000c
--- /dev/null
@@ -0,0 +1,128 @@
+// 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.
+
+// +build mips mipsle
+
+package atomic
+
+import (
+       "runtime/internal/sys"
+       "unsafe"
+)
+
+// TODO implement lock striping
+var lock struct {
+       state uint32
+       pad   [sys.CacheLineSize - 4]byte
+}
+
+//go:noescape
+func spinLock(state *uint32)
+
+//go:noescape
+func spinUnlock(state *uint32)
+
+//go:nosplit
+func lockAndCheck(addr *uint64) {
+       //  force dereference before taking lock
+       _ = *addr
+
+       spinLock(&lock.state)
+}
+
+//go:nosplit
+func unlock() {
+       spinUnlock(&lock.state)
+}
+
+//go:nosplit
+func unlockNoFence() {
+       lock.state = 0
+}
+
+//go:nosplit
+func Xadd64(addr *uint64, delta int64) (new uint64) {
+       lockAndCheck(addr)
+
+       new = *addr + uint64(delta)
+       *addr = new
+
+       unlock()
+       return
+}
+
+//go:nosplit
+func Xchg64(addr *uint64, new uint64) (old uint64) {
+       lockAndCheck(addr)
+
+       old = *addr
+       *addr = new
+
+       unlock()
+       return
+}
+
+//go:nosplit
+func Cas64(addr *uint64, old, new uint64) (swapped bool) {
+       lockAndCheck(addr)
+
+       if (*addr) == old {
+               *addr = new
+               unlock()
+               return true
+       }
+
+       unlockNoFence()
+       return false
+}
+
+//go:nosplit
+func Load64(addr *uint64) (val uint64) {
+       lockAndCheck(addr)
+
+       val = *addr
+
+       unlock()
+       return
+}
+
+//go:nosplit
+func Store64(addr *uint64, val uint64) {
+       lockAndCheck(addr)
+
+       *addr = val
+
+       unlock()
+       return
+}
+
+//go:noescape
+func Xadd(ptr *uint32, delta int32) uint32
+
+//go:noescape
+func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
+
+//go:noescape
+func Xchg(ptr *uint32, new uint32) uint32
+
+//go:noescape
+func Xchguintptr(ptr *uintptr, new uintptr) uintptr
+
+//go:noescape
+func Load(ptr *uint32) uint32
+
+//go:noescape
+func Loadp(ptr unsafe.Pointer) unsafe.Pointer
+
+//go:noescape
+func And8(ptr *uint8, val uint8)
+
+//go:noescape
+func Or8(ptr *uint8, val uint8)
+
+//go:noescape
+func Store(ptr *uint32, val uint32)
+
+// NO go:noescape annotation; see atomic_pointer.go.
+func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer)
diff --git a/src/runtime/internal/atomic/atomic_mipsx.s b/src/runtime/internal/atomic/atomic_mipsx.s
new file mode 100644 (file)
index 0000000..aeebc8f
--- /dev/null
@@ -0,0 +1,28 @@
+// 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.
+
+// +build mips mipsle
+
+#include "textflag.h"
+
+TEXT ·spinLock(SB),NOSPLIT,$0-4
+       MOVW    state+0(FP), R1
+       MOVW    $1, R2
+       SYNC
+try_lock:
+       MOVW    R2, R3
+check_again:
+       LL      (R1), R4
+       BNE     R4, check_again
+       SC      R3, (R1)
+       BEQ     R3, try_lock
+       SYNC
+       RET
+
+TEXT ·spinUnlock(SB),NOSPLIT,$0-4
+       MOVW    state+0(FP), R1
+       SYNC
+       MOVW    R0, (R1)
+       SYNC
+       RET