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