mirror of
https://github.com/golang/go
synced 2024-11-20 06:54:42 -07:00
runtime/internal/atomic: add GOARCH=mips{,le} support
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>
This commit is contained in:
parent
2c39e50995
commit
b241a06479
149
src/runtime/internal/atomic/asm_mipsx.s
Normal file
149
src/runtime/internal/atomic/asm_mipsx.s
Normal file
@ -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
|
128
src/runtime/internal/atomic/atomic_mipsx.go
Normal file
128
src/runtime/internal/atomic/atomic_mipsx.go
Normal file
@ -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)
|
28
src/runtime/internal/atomic/atomic_mipsx.s
Normal file
28
src/runtime/internal/atomic/atomic_mipsx.s
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user