| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 
 | // Copyright 2014 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"
// handleSwapUint32Fault returns the value stored in R1. Control is transferred
// to it when swapUint32 below receives SIGSEGV or SIGBUS, with the signal
// number stored in R1.
//
// It must have the same frame configuration as swapUint32 so that it can undo
// any potential call frame set up by the assembler.
TEXT handleSwapUint32Fault(SB), NOSPLIT, $0-24
	MOVW R1, sig+20(FP)
	RET
// See the corresponding doc in safecopy_unsafe.go
//
// The code is derived from Go source runtime/internal/atomic.Xchg.
//
//func swapUint32(ptr unsafe.Pointer, new uint32) (old uint32, sig int32)
TEXT ·swapUint32(SB), NOSPLIT, $0-24
	// Store 0 as the returned signal number. If we run to completion,
	// this is the value the caller will see; if a signal is received,
	// handleSwapUint32Fault will store a different value in this address.
	MOVW $0, sig+20(FP)
again:
	MOVD ptr+0(FP), R0
	MOVW new+8(FP), R1
	LDAXRW (R0), R2
	STLXRW R1, (R0), R3
	CBNZ R3, again
	MOVW R2, old+16(FP)
	RET
// func addrOfSwapUint32() uintptr
TEXT ·addrOfSwapUint32(SB), $0-8
	MOVD	$·swapUint32(SB), R0
	MOVD	R0, ret+0(FP)
	RET
// handleSwapUint64Fault returns the value stored in R1. Control is transferred
// to it when swapUint64 below receives SIGSEGV or SIGBUS, with the signal
// number stored in R1.
//
// It must have the same frame configuration as swapUint64 so that it can undo
// any potential call frame set up by the assembler.
TEXT handleSwapUint64Fault(SB), NOSPLIT, $0-28
	MOVW R1, sig+24(FP)
	RET
// See the corresponding doc in safecopy_unsafe.go
//
// The code is derived from Go source runtime/internal/atomic.Xchg64.
//
//func swapUint64(ptr unsafe.Pointer, new uint64) (old uint64, sig int32)
TEXT ·swapUint64(SB), NOSPLIT, $0-28
	// Store 0 as the returned signal number. If we run to completion,
	// this is the value the caller will see; if a signal is received,
	// handleSwapUint64Fault will store a different value in this address.
	MOVW $0, sig+24(FP)
again:
	MOVD ptr+0(FP), R0
	MOVD new+8(FP), R1
	LDAXR (R0), R2
	STLXR R1, (R0), R3
	CBNZ R3, again
	MOVD R2, old+16(FP)
	RET
// func addrOfSwapUint64() uintptr
TEXT ·addrOfSwapUint64(SB), $0-8
	MOVD	$·swapUint64(SB), R0
	MOVD	R0, ret+0(FP)
	RET
// handleCompareAndSwapUint32Fault returns the value stored in R1. Control is
// transferred to it when compareAndSwapUint32 below receives SIGSEGV or SIGBUS,
// with the signal number stored in R1.
//
// It must have the same frame configuration as compareAndSwapUint32 so that it
// can undo any potential call frame set up by the assembler.
TEXT handleCompareAndSwapUint32Fault(SB), NOSPLIT, $0-24
	MOVW R1, sig+20(FP)
	RET
// See the corresponding doc in safecopy_unsafe.go
//
// The code is derived from Go source runtime/internal/atomic.Cas.
//
//func compareAndSwapUint32(ptr unsafe.Pointer, old, new uint32) (prev uint32, sig int32)
TEXT ·compareAndSwapUint32(SB), NOSPLIT, $0-24
	// Store 0 as the returned signal number. If we run to completion, this is
	// the value the caller will see; if a signal is received,
	// handleCompareAndSwapUint32Fault will store a different value in this
	// address.
	MOVW $0, sig+20(FP)
	MOVD ptr+0(FP), R0
	MOVW old+8(FP), R1
	MOVW new+12(FP), R2
again:
	LDAXRW (R0), R3
	CMPW R1, R3
	BNE done
	STLXRW R2, (R0), R4
	CBNZ R4, again
done:
	MOVW R3, prev+16(FP)
	RET
// func addrOfCompareAndSwapUint32() uintptr
TEXT ·addrOfCompareAndSwapUint32(SB), $0-8
	MOVD	$·compareAndSwapUint32(SB), R0
	MOVD	R0, ret+0(FP)
	RET
// handleLoadUint32Fault returns the value stored in DI. Control is transferred
// to it when LoadUint32 below receives SIGSEGV or SIGBUS, with the signal
// number stored in DI.
//
// It must have the same frame configuration as loadUint32 so that it can undo
// any potential call frame set up by the assembler.
TEXT handleLoadUint32Fault(SB), NOSPLIT, $0-16
	MOVW R1, sig+12(FP)
	RET
// loadUint32 atomically loads *ptr and returns it. If a SIGSEGV or SIGBUS
// signal is received, the value returned is unspecified, and sig is the number
// of the signal that was received.
//
// Preconditions: ptr must be aligned to a 4-byte boundary.
//
//func loadUint32(ptr unsafe.Pointer) (val uint32, sig int32)
TEXT ·loadUint32(SB), NOSPLIT, $0-16
	// Store 0 as the returned signal number. If we run to completion,
	// this is the value the caller will see; if a signal is received,
	// handleLoadUint32Fault will store a different value in this address.
	MOVW $0, sig+12(FP)
	MOVD ptr+0(FP), R0
	LDARW (R0), R1
	MOVW R1, val+8(FP)
	RET
// func addrOfLoadUint32() uintptr
TEXT ·addrOfLoadUint32(SB), $0-8
	MOVD	$·loadUint32(SB), R0
	MOVD	R0, ret+0(FP)
	RET
 |