xref: /titanic_51/usr/src/uts/intel/ia32/sys/asm_linkage.h (revision 613a2f6ba31e891e3d947a356daf5e563d43c1ce)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef _IA32_SYS_ASM_LINKAGE_H
28 #define	_IA32_SYS_ASM_LINKAGE_H
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #include <sys/stack.h>
33 #include <sys/trap.h>
34 
35 #ifdef	__cplusplus
36 extern "C" {
37 #endif
38 
39 #ifdef _ASM	/* The remainder of this file is only for assembly files */
40 
41 /*
42  * make annoying differences in assembler syntax go away
43  */
44 
45 /*
46  * D16 and A16 are used to insert instructions prefixes; the
47  * macros help the assembler code be slightly more portable.
48  */
49 #if !defined(__GNUC_AS__)
50 /*
51  * /usr/ccs/bin/as prefixes are parsed as separate instructions
52  */
53 #define	D16	data16;
54 #define	A16	addr16;
55 
56 /*
57  * (There are some weird constructs in constant expressions)
58  */
59 #define	_CONST(const)		[const]
60 #define	_BITNOT(const)		-1!_CONST(const)
61 #define	_MUL(a, b)		_CONST(a \* b)
62 
63 #else
64 /*
65  * Why not use the 'data16' and 'addr16' prefixes .. well, the
66  * assembler doesn't quite believe in real mode, and thus argues with
67  * us about what we're trying to do.
68  */
69 #define	D16	.byte	0x66;
70 #define	A16	.byte	0x67;
71 
72 #define	_CONST(const)		(const)
73 #define	_BITNOT(const)		~_CONST(const)
74 #define	_MUL(a, b)		_CONST(a * b)
75 
76 #endif
77 
78 /*
79  * C pointers are different sizes between i386 and amd64.
80  * These constants can be used to compute offsets into pointer arrays.
81  */
82 #if defined(__amd64)
83 #define	CLONGSHIFT	3
84 #define	CLONGSIZE	8
85 #define	CLONGMASK	7
86 #elif defined(__i386)
87 #define	CLONGSHIFT	2
88 #define	CLONGSIZE	4
89 #define	CLONGMASK	3
90 #endif
91 
92 /*
93  * Since we know we're either ILP32 or LP64 ..
94  */
95 #define	CPTRSHIFT	CLONGSHIFT
96 #define	CPTRSIZE	CLONGSIZE
97 #define	CPTRMASK	CLONGMASK
98 
99 #if CPTRSIZE != (1 << CPTRSHIFT) || CLONGSIZE != (1 << CLONGSHIFT)
100 #error	"inconsistent shift constants"
101 #endif
102 
103 #if CPTRMASK != (CPTRSIZE - 1) || CLONGMASK != (CLONGSIZE - 1)
104 #error	"inconsistent mask constants"
105 #endif
106 
107 #define	ASM_ENTRY_ALIGN	16
108 
109 /*
110  * SSE register alignment and save areas
111  */
112 
113 #define	XMM_SIZE	16
114 #define	XMM_ALIGN	16
115 
116 #if defined(__amd64)
117 
118 #define	SAVE_XMM_PROLOG(sreg, nreg)				\
119 	subq	$_CONST(_MUL(XMM_SIZE, nreg)), %rsp;		\
120 	movq	%rsp, sreg
121 
122 #define	RSTOR_XMM_EPILOG(sreg, nreg)				\
123 	addq	$_CONST(_MUL(XMM_SIZE, nreg)), %rsp
124 
125 #elif defined(__i386)
126 
127 #define	SAVE_XMM_PROLOG(sreg, nreg)				\
128 	subl	$_CONST(_MUL(XMM_SIZE, nreg) + XMM_ALIGN), %esp; \
129 	movl	%esp, sreg;					\
130 	addl	$XMM_ALIGN, sreg;				\
131 	andl	$_BITNOT(XMM_ALIGN-1), sreg
132 
133 #define	RSTOR_XMM_EPILOG(sreg, nreg)				\
134 	addl	$_CONST(_MUL(XMM_SIZE, nreg) + XMM_ALIGN), %esp;
135 
136 #endif	/* __i386 */
137 
138 /*
139  * profiling causes definitions of the MCOUNT and RTMCOUNT
140  * particular to the type
141  */
142 #ifdef GPROF
143 
144 #define	MCOUNT(x) \
145 	pushl	%ebp; \
146 	movl	%esp, %ebp; \
147 	call	_mcount; \
148 	popl	%ebp
149 
150 #endif /* GPROF */
151 
152 #ifdef PROF
153 
154 #define	MCOUNT(x) \
155 /* CSTYLED */ \
156 	.lcomm .L_/**/x/**/1, 4, 4; \
157 	pushl	%ebp; \
158 	movl	%esp, %ebp; \
159 /* CSTYLED */ \
160 	movl	$.L_/**/x/**/1, %edx; \
161 	call	_mcount; \
162 	popl	%ebp
163 
164 #endif /* PROF */
165 
166 /*
167  * if we are not profiling, MCOUNT should be defined to nothing
168  */
169 #if !defined(PROF) && !defined(GPROF)
170 #define	MCOUNT(x)
171 #endif /* !defined(PROF) && !defined(GPROF) */
172 
173 #define	RTMCOUNT(x)	MCOUNT(x)
174 
175 /*
176  * Macro to define weak symbol aliases. These are similar to the ANSI-C
177  *	#pragma weak _name = name
178  * except a compiler can determine type. The assembler must be told. Hence,
179  * the second parameter must be the type of the symbol (i.e.: function,...)
180  */
181 #define	ANSI_PRAGMA_WEAK(sym, stype)	\
182 /* CSTYLED */ \
183 	.weak	_/**/sym; \
184 /* CSTYLED */ \
185 	.type	_/**/sym, @stype; \
186 /* CSTYLED */ \
187 _/**/sym = sym
188 
189 /*
190  * Like ANSI_PRAGMA_WEAK(), but for unrelated names, as in:
191  *	#pragma weak sym1 = sym2
192  */
193 #define	ANSI_PRAGMA_WEAK2(sym1, sym2, stype)	\
194 	.weak	sym1; \
195 	.type sym1, @stype; \
196 sym1	= sym2
197 
198 /*
199  * ENTRY provides the standard procedure entry code and an easy way to
200  * insert the calls to mcount for profiling. ENTRY_NP is identical, but
201  * never calls mcount.
202  */
203 #define	ENTRY(x) \
204 	.text; \
205 	.align	ASM_ENTRY_ALIGN; \
206 	.globl	x; \
207 	.type	x, @function; \
208 x:	MCOUNT(x)
209 
210 #define	ENTRY_NP(x) \
211 	.text; \
212 	.align	ASM_ENTRY_ALIGN; \
213 	.globl	x; \
214 	.type	x, @function; \
215 x:
216 
217 #define	RTENTRY(x) \
218 	.text; \
219 	.align	ASM_ENTRY_ALIGN; \
220 	.globl	x; \
221 	.type	x, @function; \
222 x:	RTMCOUNT(x)
223 
224 /*
225  * ENTRY2 is identical to ENTRY but provides two labels for the entry point.
226  */
227 #define	ENTRY2(x, y) \
228 	.text; \
229 	.align	ASM_ENTRY_ALIGN; \
230 	.globl	x, y; \
231 	.type	x, @function; \
232 	.type	y, @function; \
233 /* CSTYLED */ \
234 x:	; \
235 y:	MCOUNT(x)
236 
237 #define	ENTRY_NP2(x, y) \
238 	.text; \
239 	.align	ASM_ENTRY_ALIGN; \
240 	.globl	x, y; \
241 	.type	x, @function; \
242 	.type	y, @function; \
243 /* CSTYLED */ \
244 x:	; \
245 y:
246 
247 
248 /*
249  * ALTENTRY provides for additional entry points.
250  */
251 #define	ALTENTRY(x) \
252 	.globl x; \
253 	.type	x, @function; \
254 x:
255 
256 /*
257  * DGDEF and DGDEF2 provide global data declarations.
258  *
259  * DGDEF provides a word aligned word of storage.
260  *
261  * DGDEF2 allocates "sz" bytes of storage with **NO** alignment.  This
262  * implies this macro is best used for byte arrays.
263  *
264  * DGDEF3 allocates "sz" bytes of storage with "algn" alignment.
265  */
266 #define	DGDEF2(name, sz) \
267 	.data; \
268 	.globl	name; \
269 	.type	name, @object; \
270 	.size	name, sz; \
271 name:
272 
273 #define	DGDEF3(name, sz, algn) \
274 	.data; \
275 	.align	algn; \
276 	.globl	name; \
277 	.type	name, @object; \
278 	.size	name, sz; \
279 name:
280 
281 #define	DGDEF(name)	DGDEF3(name, 4, 4)
282 
283 /*
284  * SET_SIZE trails a function and set the size for the ELF symbol table.
285  */
286 #define	SET_SIZE(x) \
287 	.size	x, [.-x]
288 
289 /*
290  * NWORD provides native word value.
291  */
292 #if defined(__amd64)
293 
294 /*CSTYLED*/
295 #define	NWORD	quad
296 
297 #elif defined(__i386)
298 
299 #define	NWORD	long
300 
301 #endif  /* __i386 */
302 
303 #endif /* _ASM */
304 
305 #ifdef	__cplusplus
306 }
307 #endif
308 
309 #endif	/* _IA32_SYS_ASM_LINKAGE_H */
310