xref: /titanic_51/usr/src/uts/intel/ia32/sys/asm_linkage.h (revision e07d9cb85217949d497b02d7211de8a197d2f2eb)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 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 	.weak	sym; \
183 	.type sym, @stype; \
184 /* CSTYLED */ \
185 sym	= _/**/sym
186 
187 /*
188  * Like ANSI_PRAGMA_WEAK(), but for unrelated names, as in:
189  *	#pragma weak sym1 = sym2
190  */
191 #define	ANSI_PRAGMA_WEAK2(sym1, sym2, stype)	\
192 	.weak	sym1; \
193 	.type sym1, @stype; \
194 sym1	= sym2
195 
196 /*
197  * ENTRY provides the standard procedure entry code and an easy way to
198  * insert the calls to mcount for profiling. ENTRY_NP is identical, but
199  * never calls mcount.
200  */
201 #define	ENTRY(x) \
202 	.text; \
203 	.align	ASM_ENTRY_ALIGN; \
204 	.globl	x; \
205 	.type	x, @function; \
206 x:	MCOUNT(x)
207 
208 #define	ENTRY_NP(x) \
209 	.text; \
210 	.align	ASM_ENTRY_ALIGN; \
211 	.globl	x; \
212 	.type	x, @function; \
213 x:
214 
215 #define	RTENTRY(x) \
216 	.text; \
217 	.align	ASM_ENTRY_ALIGN; \
218 	.globl	x; \
219 	.type	x, @function; \
220 x:	RTMCOUNT(x)
221 
222 /*
223  * ENTRY2 is identical to ENTRY but provides two labels for the entry point.
224  */
225 #define	ENTRY2(x, y) \
226 	.text; \
227 	.align	ASM_ENTRY_ALIGN; \
228 	.globl	x, y; \
229 	.type	x, @function; \
230 	.type	y, @function; \
231 /* CSTYLED */ \
232 x:	; \
233 y:	MCOUNT(x)
234 
235 #define	ENTRY_NP2(x, y) \
236 	.text; \
237 	.align	ASM_ENTRY_ALIGN; \
238 	.globl	x, y; \
239 	.type	x, @function; \
240 	.type	y, @function; \
241 /* CSTYLED */ \
242 x:	; \
243 y:
244 
245 
246 /*
247  * ALTENTRY provides for additional entry points.
248  */
249 #define	ALTENTRY(x) \
250 	.globl x; \
251 	.type	x, @function; \
252 x:
253 
254 /*
255  * DGDEF and DGDEF2 provide global data declarations.
256  *
257  * DGDEF provides a word aligned word of storage.
258  *
259  * DGDEF2 allocates "sz" bytes of storage with **NO** alignment.  This
260  * implies this macro is best used for byte arrays.
261  *
262  * DGDEF3 allocates "sz" bytes of storage with "algn" alignment.
263  */
264 #define	DGDEF2(name, sz) \
265 	.data; \
266 	.globl	name; \
267 	.type	name, @object; \
268 	.size	name, sz; \
269 name:
270 
271 #define	DGDEF3(name, sz, algn) \
272 	.data; \
273 	.align	algn; \
274 	.globl	name; \
275 	.type	name, @object; \
276 	.size	name, sz; \
277 name:
278 
279 #define	DGDEF(name)	DGDEF3(name, 4, 4)
280 
281 /*
282  * SET_SIZE trails a function and set the size for the ELF symbol table.
283  */
284 #define	SET_SIZE(x) \
285 	.size	x, [.-x]
286 
287 /*
288  * NWORD provides native word value.
289  */
290 #if defined(__amd64)
291 
292 /*CSTYLED*/
293 #define	NWORD	quad
294 
295 #elif defined(__i386)
296 
297 #define	NWORD	long
298 
299 #endif  /* __i386 */
300 
301 #endif /* _ASM */
302 
303 #ifdef	__cplusplus
304 }
305 #endif
306 
307 #endif	/* _IA32_SYS_ASM_LINKAGE_H */
308