1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2001 Jake Burkholder.
5  * Copyright (c) 2011 Marius Strobl <marius@FreeBSD.org>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD: stable/12/sys/sparc64/include/asmacros.h 326262 2017-11-27 15:10:39Z pfg $
30  */
31 
32 #ifndef	_MACHINE_ASMACROS_H_
33 #define	_MACHINE_ASMACROS_H_
34 
35 #ifdef _KERNEL
36 
37 /*
38  * Normal and alternate %g6 point to the pcb of the current process.  Normal,
39  * alternate and interrupt %g7 point to per-cpu data.
40  */
41 #define	PCB_REG		%g6
42 #define	PCPU_REG	%g7
43 
44 /*
45  * Alternate %g5 points to a per-cpu panic stack, which is used as a last
46  * resort, and for temporarily saving alternate globals.
47  */
48 #define	ASP_REG		%g5
49 
50 #ifdef LOCORE
51 
52 /*
53  * Atomically decrement an integer in memory.
54  */
55 #define	ATOMIC_DEC_INT(r1, r2, r3)					\
56 	lduw	[r1], r2 ;						\
57 9:	sub	r2, 1, r3 ;						\
58 	casa	[r1] ASI_N, r2, r3 ;					\
59 	cmp	r2, r3 ;						\
60 	bne,pn	%icc, 9b ;						\
61 	 mov	r3, r2
62 
63 /*
64  * Atomically increment an integer in memory.
65  */
66 #define	ATOMIC_INC_INT(r1, r2, r3)					\
67 	lduw	[r1], r2 ;						\
68 9:	add	r2, 1, r3 ;						\
69 	casa	[r1] ASI_N, r2, r3 ;					\
70 	cmp	r2, r3 ;						\
71 	bne,pn	%icc, 9b ;						\
72 	 mov	r3, r2
73 
74 /*
75  * Atomically increment a long in memory.
76  */
77 #define	ATOMIC_INC_LONG(r1, r2, r3)					\
78 	ldx	[r1], r2 ;						\
79 9:	add	r2, 1, r3 ;						\
80 	casxa	[r1] ASI_N, r2, r3 ;					\
81 	cmp	r2, r3 ;						\
82 	bne,pn	%xcc, 9b ;						\
83 	 mov	r3, r2
84 
85 /*
86  * Atomically clear a number of bits of an integer in memory.
87  */
88 #define	ATOMIC_CLEAR_INT(r1, r2, r3, bits)				\
89 	lduw	[r1], r2 ;						\
90 9:	andn	r2, bits, r3 ;						\
91 	casa	[r1] ASI_N, r2, r3 ;					\
92 	cmp	r2, r3 ;						\
93 	bne,pn	%icc, 9b ;						\
94 	 mov	r3, r2
95 
96 /*
97  * Atomically clear a number of bits of a long in memory.
98  */
99 #define	ATOMIC_CLEAR_LONG(r1, r2, r3, bits)				\
100 	ldx	[r1], r2 ;						\
101 9:	andn	r2, bits, r3 ;						\
102 	casxa	[r1] ASI_N, r2, r3 ;					\
103 	cmp	r2, r3 ;						\
104 	bne,pn	%xcc, 9b ;						\
105 	 mov	r3, r2
106 
107 /*
108  * Atomically load an integer from memory.
109  */
110 #define	ATOMIC_LOAD_INT(r1, val)					\
111 	clr	val ;							\
112 	casa	[r1] ASI_N, %g0, val
113 
114 /*
115  * Atomically load a long from memory.
116  */
117 #define	ATOMIC_LOAD_LONG(r1, val)					\
118 	clr	val ;							\
119 	casxa	[r1] ASI_N, %g0, val
120 
121 /*
122  * Atomically set a number of bits of an integer in memory.
123  */
124 #define	ATOMIC_SET_INT(r1, r2, r3, bits)				\
125 	lduw	[r1], r2 ;						\
126 9:	or	r2, bits, r3 ;						\
127 	casa	[r1] ASI_N, r2, r3 ;					\
128 	cmp	r2, r3 ;						\
129 	bne,pn	%icc, 9b ;						\
130 	 mov	r3, r2
131 
132 /*
133  * Atomically set a number of bits of a long in memory.
134  */
135 #define	ATOMIC_SET_LONG(r1, r2, r3, bits)				\
136 	ldx	[r1], r2 ;						\
137 9:	or	r2, bits, r3 ;						\
138 	casxa	[r1] ASI_N, r2, r3 ;					\
139 	cmp	r2, r3 ;						\
140 	bne,pn	%xcc, 9b ;						\
141 	 mov	r3, r2
142 
143 /*
144  * Atomically store an integer in memory.
145  */
146 #define	ATOMIC_STORE_INT(r1, r2, r3, val)				\
147 	lduw	[r1], r2 ;						\
148 9:	mov	val, r3 ;						\
149 	casa	[r1] ASI_N, r2, r3 ;					\
150 	cmp	r2, r3 ;						\
151 	bne,pn	%icc, 9b ;						\
152 	 mov	r3, r2
153 
154 /*
155  * Atomically store a long in memory.
156  */
157 #define	ATOMIC_STORE_LONG(r1, r2, r3, val)				\
158 	ldx	[r1], r2 ;						\
159 9:	mov	val, r3 ;						\
160 	casxa	[r1] ASI_N, r2, r3 ;					\
161 	cmp	r2, r3 ;						\
162 	bne,pn	%xcc, 9b ;						\
163 	 mov	r3, r2
164 
165 #define	PCPU(member)	PCPU_REG + PC_ ## member
166 #define	PCPU_ADDR(member, reg)						\
167 	add	PCPU_REG, PC_ ## member, reg
168 
169 #define	DEBUGGER()							\
170 	ta	%xcc, 1
171 
172 #define	PANIC(msg, r1)							\
173 	.sect	.rodata ;						\
174 9:	.asciz	msg ;							\
175 	.previous ;							\
176 	SET(9b, r1, %o0) ;						\
177 	call	panic ;							\
178 	 nop
179 
180 #ifdef INVARIANTS
181 #define	KASSERT(r1, msg)						\
182 	brnz,pt	r1, 8f ;						\
183 	 nop ;								\
184 	PANIC(msg, r1) ;						\
185 8:
186 #else
187 #define	KASSERT(r1, msg)
188 #endif
189 
190 #define	PUTS(msg, r1)							\
191 	.sect	.rodata ;						\
192 9:	.asciz	msg ;							\
193 	.previous ;							\
194 	SET(9b, r1, %o0) ;						\
195 	call	printf ;						\
196 	 nop
197 
198 #define	_ALIGN_DATA	.align 8
199 
200 #define	DATA(name)							\
201 	.data ;								\
202 	_ALIGN_DATA ;							\
203 	.globl	name ;							\
204 	.type	name, @object ;						\
205 name:
206 
207 #define	EMPTY
208 
209 /*
210  * Generate atomic compare and swap, load and store instructions for the
211  * corresponding width and ASI (or not).  Note that we want to evaluate the
212  * macro args before concatenating, so that EMPTY really turns into nothing.
213  */
214 #define		_LD(w, a)	ld ## w ## a
215 #define		_ST(w, a)	st ## w ## a
216 #define		_CAS(w, a)	cas ## w ## a
217 
218 #define		LD(w, a)	_LD(w, a)
219 #define		ST(w, a)	_ST(w, a)
220 #define		CAS(w, a)	_CAS(w, a)
221 
222 #endif /* LOCORE */
223 
224 #endif /* _KERNEL */
225 
226 #endif /* !_MACHINE_ASMACROS_H_ */
227