xref: /netbsd-src/common/lib/libc/arch/sparc/atomic/atomic_cas.S (revision dd367c0e943ca553343cad1291b7ab83f1aefa1a)
1*dd367c0eSmartin/*	$NetBSD: atomic_cas.S,v 1.13 2014/02/21 16:21:02 martin Exp $	*/
2ebe806aaSad
3ebe806aaSad/*-
4646fc3baSad * Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
5ebe806aaSad * All rights reserved.
6ebe806aaSad *
7ebe806aaSad * This code is derived from software contributed to The NetBSD Foundation
8ebe806aaSad * by Andrew Doran and Jason R. Thorpe.
9ebe806aaSad *
10ebe806aaSad * Redistribution and use in source and binary forms, with or without
11ebe806aaSad * modification, are permitted provided that the following conditions
12ebe806aaSad * are met:
13ebe806aaSad * 1. Redistributions of source code must retain the above copyright
14ebe806aaSad *    notice, this list of conditions and the following disclaimer.
15ebe806aaSad * 2. Redistributions in binary form must reproduce the above copyright
16ebe806aaSad *    notice, this list of conditions and the following disclaimer in the
17ebe806aaSad *    documentation and/or other materials provided with the distribution.
18ebe806aaSad *
19ebe806aaSad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20ebe806aaSad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21ebe806aaSad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22ebe806aaSad * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23ebe806aaSad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24ebe806aaSad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25ebe806aaSad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26ebe806aaSad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27ebe806aaSad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28ebe806aaSad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29ebe806aaSad * POSSIBILITY OF SUCH DAMAGE.
30ebe806aaSad */
31ebe806aaSad
32654753c2Spooka#include <sys/param.h>
33ebe806aaSad#include "atomic_op_asm.h"
34ebe806aaSad
35fd33b05eSnakayama#if defined(_HARDKERNEL)
36ebe806aaSad
3796f5ce86Sad#include <machine/psl.h>
3896f5ce86Sad
39ebe806aaSad#include "opt_multiprocessor.h"
40ebe806aaSad
41ebe806aaSad#define	DISABLE_INTERRUPTS						 \
4296f5ce86Sad	rd	%psr, %o4			/* disable interrupts */;\
4396f5ce86Sad	or	%o4, PSR_PIL, %o5					;\
44ebe806aaSad	wr	%o5, 0, %psr						;\
45ebe806aaSad	nop								;\
46ebe806aaSad	nop								;\
47ebe806aaSad	nop
48ebe806aaSad
49ebe806aaSad#define	RESTORE_INTERRUPTS						 \
5096f5ce86Sad	wr	%o4, 0, %psr			/* enable interrupts */	;\
51ebe806aaSad	nop								;\
52ebe806aaSad	nop								;\
53ebe806aaSad	nop
54ebe806aaSad
55132ffc21Spooka#else	/* _HARDKERNEL */
561206a8cbSad
571206a8cbSad#define	MULTIPROCESSOR	1
581206a8cbSad#define	DISABLE_INTERRUPTS		/* nothing */
591206a8cbSad#define	RESTORE_INTERRUPTS		/* nothing */
601206a8cbSad
61132ffc21Spooka#endif	/* _HARDKERNEL */
621206a8cbSad
63ebe806aaSad#if defined(MULTIPROCESSOR)
64ebe806aaSad	.section .bss
65ebe806aaSad	.align	1024
664d12bfcdSjoerg#ifdef __PIC__
67f3da52f3Spooka	.globl _C_LABEL(_atomic_cas_locktab)
68f3da52f3Spooka#endif
69ebe806aaSadOTYPE(_C_LABEL(_atomic_cas_locktab))
70ebe806aaSad_C_LABEL(_atomic_cas_locktab):
71ebe806aaSad	.space	1024
72ebe806aaSad
734d12bfcdSjoerg#ifdef __PIC__
74f3da52f3Spooka/* o4 is not used for PSR in PIC cases, so we can use it here */
75f3da52f3Spooka#define GETLOCKTAB							\
76f3da52f3Spooka	PIC_PROLOGUE(%o3,%o4)						;\
77f3da52f3Spooka	set _C_LABEL(_atomic_cas_locktab), %o4				;\
78f3da52f3Spooka	ld [%o3 + %o4], %o3
79f3da52f3Spooka#else
80f3da52f3Spooka#define GETLOCKTAB							\
81f3da52f3Spooka	sethi	%hi(_C_LABEL(_atomic_cas_locktab)), %o3
82f3da52f3Spooka#endif
83f3da52f3Spooka
84ebe806aaSad#define	ACQUIRE_INTERLOCK						 \
85ebe806aaSad	DISABLE_INTERRUPTS						;\
8696f5ce86Sad	srl	%o0, 3, %o5			/* get lock address */	;\
87ebe806aaSad	and	%o5, 1023, %o5						;\
88f3da52f3Spooka	GETLOCKTAB							;\
89ebe806aaSad	add	%o5, %o3, %o5						;\
90ebe806aaSad									;\
9196f5ce86Sad	/* %o5 has interlock address */					;\
92ebe806aaSad									;\
9396f5ce86Sad1:	ldstub	[%o5], %o3			/* acquire lock */	;\
94ebe806aaSad	tst	%o3							;\
95ebe806aaSad	bz,a	2f							;\
96ebe806aaSad	 nop								;\
97ebe806aaSad	nop								;\
98ebe806aaSad	nop								;\
9996f5ce86Sad	b,a	1b				/* spin	*/		;\
100ebe806aaSad	 nop								;\
10196f5ce86Sad	/* We now hold the interlock */					;\
102ebe806aaSad2:
103ebe806aaSad
104ebe806aaSad#define	RELEASE_INTERLOCK						 \
10596f5ce86Sad	stb	%g0, [%o5]			/* release interlock */	;\
106ebe806aaSad	RESTORE_INTERRUPTS
107ebe806aaSad
108ebe806aaSad#else /* ! MULTIPROCESSOR */
109ebe806aaSad
110ebe806aaSad#define	ACQUIRE_INTERLOCK	DISABLE_INTERRUPTS
111ebe806aaSad
112ebe806aaSad#define	RELEASE_INTERLOCK	RESTORE_INTERRUPTS
113ebe806aaSad
114ebe806aaSad#endif /* MULTIPROCESSOR */
115ebe806aaSad
116ebe806aaSad	.text
117ebe806aaSad
118ebe806aaSad/*
119ebe806aaSad * The v7 and v8 SPARC doesn't have compare-and-swap, so we block interrupts
120ebe806aaSad * and use an interlock.
121ebe806aaSad *
122ebe806aaSad * XXX On single CPU systems, this should use a restartable sequence:
123ebe806aaSad * XXX there we don't need the overhead of interlocking.
124ebe806aaSad *
125ebe806aaSad * XXX NOTE!  The interlock trick only works if EVERYTHING writes to
126ebe806aaSad * XXX the memory cell through this code path!
127ebe806aaSad */
1286740bb54SchsENTRY(_atomic_cas_32)
129ebe806aaSad	ACQUIRE_INTERLOCK
130ebe806aaSad	! %o4 has saved PSR value
131ebe806aaSad	! %o5 has interlock address
132ebe806aaSad
133ebe806aaSad	ld	[%o0], %o3			! get old value
134ebe806aaSad	cmp	%o1, %o3			! old == new?
135ebe806aaSad	beq,a	3f				! yes, do the store
136ebe806aaSad	 st	%o2, [%o0]			! (in the delay slot)
137ebe806aaSad
138ebe806aaSad3:	RELEASE_INTERLOCK
139ebe806aaSad
140ebe806aaSad	retl
141ebe806aaSad	 mov	%o3, %o0			! return old value
142ebe806aaSad
143ebe806aaSadATOMIC_OP_ALIAS(atomic_cas_32,_atomic_cas_32)
144ebe806aaSadATOMIC_OP_ALIAS(atomic_cas_uint,_atomic_cas_32)
145ebe806aaSadSTRONG_ALIAS(_atomic_cas_uint,_atomic_cas_32)
146ebe806aaSadATOMIC_OP_ALIAS(atomic_cas_ulong,_atomic_cas_32)
147ebe806aaSadSTRONG_ALIAS(_atomic_cas_ulong,_atomic_cas_32)
148ebe806aaSadATOMIC_OP_ALIAS(atomic_cas_ptr,_atomic_cas_32)
149ebe806aaSadSTRONG_ALIAS(_atomic_cas_ptr,_atomic_cas_32)
150*dd367c0eSmartinSTRONG_ALIAS(__sync_val_compare_and_swap_4,_atomic_cas_32)
151646fc3baSad
152646fc3baSadATOMIC_OP_ALIAS(atomic_cas_32_ni,_atomic_cas_32)
153646fc3baSadSTRONG_ALIAS(_atomic_cas_32_ni,_atomic_cas_32)
154646fc3baSadATOMIC_OP_ALIAS(atomic_cas_uint_ni,_atomic_cas_32)
155646fc3baSadSTRONG_ALIAS(_atomic_cas_uint_ni,_atomic_cas_32)
156646fc3baSadATOMIC_OP_ALIAS(atomic_cas_ulong_ni,_atomic_cas_32)
157646fc3baSadSTRONG_ALIAS(_atomic_cas_ulong_ni,_atomic_cas_32)
158646fc3baSadATOMIC_OP_ALIAS(atomic_cas_ptr_ni,_atomic_cas_32)
159646fc3baSadSTRONG_ALIAS(_atomic_cas_ptr_ni,_atomic_cas_32)
160