1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31/*
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
49 *  School of Computer Science
50 *  Carnegie Mellon University
51 *  Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56
57#ifndef	_I386_ASM_H_
58#define	_I386_ASM_H_
59
60#ifdef _KERNEL
61#include <gprof.h>
62#endif	/* _KERNEL */
63
64#if	defined(MACH_KERNEL) || defined(_KERNEL)
65#include <gprof.h>
66#endif	/* MACH_KERNEL || _KERNEL */
67
68#if defined(__i386__)
69
70#define S_PC	 (%esp)
71#define S_ARG0	 4(%esp)
72#define S_ARG1	 8(%esp)
73#define S_ARG2	12(%esp)
74#define S_ARG3	16(%esp)
75#define S_ARG4	20(%esp)
76
77#define FRAME	pushl %ebp; movl %esp, %ebp
78#define EMARF	leave
79
80#define B_LINK	 (%ebp)
81#define B_PC	 4(%ebp)
82#define B_ARG0	 8(%ebp)
83#define B_ARG1	12(%ebp)
84#define B_ARG2	16(%ebp)
85#define B_ARG3	20(%ebp)
86
87#elif defined(__x86_64__)
88
89#define S_PC	 (%rsp)
90
91#define FRAME	pushq %rbp; movq %rsp, %rbp
92#define EMARF	leave
93
94#define B_LINK	 (%rbp)
95#define B_PC	 8(%rbp)
96
97#else
98#error unsupported architecture
99#endif
100
101/* There is another definition of ALIGN for .c sources */
102#ifdef ASSEMBLER
103#define ALIGN 4,0x90
104#endif /* ASSEMBLER */
105
106#ifndef FALIGN
107#define FALIGN ALIGN
108#endif
109
110#define LB(x,n) n
111#if	__STDC__
112#ifndef __NO_UNDERSCORES__
113#define	LCL(x)	L ## x
114#define EXT(x) _ ## x
115#define LEXT(x) _ ## x ## :
116#else
117#define	LCL(x)	.L ## x
118#define EXT(x) x
119#define LEXT(x) x ## :
120#endif
121#define LBc(x,n) n ## :
122#define LBb(x,n) n ## b
123#define LBf(x,n) n ## f
124#else /* __STDC__ */
125#ifndef __NO_UNDERSCORES__
126#define LCL(x) L/**/x
127#define EXT(x) _/**/x
128#define LEXT(x) _/**/x/**/:
129#else /* __NO_UNDERSCORES__ */
130#define	LCL(x)	.L/**/x
131#define EXT(x) x
132#define LEXT(x) x/**/:
133#endif /* __NO_UNDERSCORES__ */
134#define LBc(x,n) n/**/:
135#define LBb(x,n) n/**/b
136#define LBf(x,n) n/**/f
137#endif /* __STDC__ */
138
139#define SVC .byte 0x9a; .long 0; .word 0x7
140
141#define RPC_SVC .byte 0x9a; .long 0; .word 0xf
142
143#define String	.asciz
144#define Value	.word
145#define Times(a,b) (a*b)
146#define Divide(a,b) (a/b)
147
148#define INB	inb	%dx, %al
149#define OUTB	outb	%al, %dx
150#define INL	inl	%dx, %eax
151#define OUTL	outl	%eax, %dx
152
153#define data16	.byte 0x66
154#define addr16	.byte 0x67
155
156#if !GPROF
157#define MCOUNT
158
159#elif defined(__SHARED__)
160#define MCOUNT		; .data;\
161			.align ALIGN;\
162			LBc(x, 8) .long 0;\
163			.text;\
164			Gpush;\
165			Gload;\
166			leal Gotoff(LBb(x,8)),%edx;\
167			Egaddr(%eax,_mcount_ptr);\
168			Gpop;\
169			call *(%eax);
170
171#else	/* !GPROF, !__SHARED__ */
172#define MCOUNT		; call mcount;
173#endif /* GPROF */
174
175#ifdef __ELF__
176#define ELF_FUNC(x)	.type x,@function
177#define ELF_DATA(x)	.type x,@object
178#define ELF_SIZE(x,s)	.size x,s
179#else
180#define ELF_FUNC(x)
181#define ELF_DATA(x)
182#define ELF_SIZE(x,s)
183#endif
184
185#define	Entry(x)	.globl EXT(x); ELF_FUNC(EXT(x)); .align FALIGN; LEXT(x)
186#define	ENTRY(x)	Entry(x) MCOUNT
187#define	ENTRY2(x,y)	.globl EXT(x); .globl EXT(y); \
188			ELF_FUNC(EXT(x)); ELF_FUNC(EXT(y)); \
189			.align FALIGN; LEXT(x); LEXT(y) \
190			MCOUNT
191#if __STDC__
192#define	ASENTRY(x) 	.globl x; .align FALIGN; x ## : ELF_FUNC(x) MCOUNT
193#else
194#define	ASENTRY(x) 	.globl x; .align FALIGN; x: ELF_FUNC(x) MCOUNT
195#endif /* __STDC__ */
196
197#define	DATA(x)		.globl EXT(x); ELF_DATA(EXT(x)); .align ALIGN; LEXT(x)
198
199#define End(x)		ELF_SIZE(x,.-x)
200#define END(x)		End(EXT(x))
201#define ENDDATA(x)	END(x)
202#define Enddata(x)	End(x)
203
204/*
205 * ELF shared library accessor macros.
206 * Gpush saves the %ebx register used for the GOT address
207 * Gpop pops %ebx if we need a GOT
208 * Gload loads %ebx with the GOT address if shared libraries are used
209 * Gcall calls an external function.
210 * Gotoff allows you to reference local labels.
211 * Gotoff2 allows you to reference local labels with an index reg.
212 * Gotoff3 allows you to reference local labels with an index reg & size.
213 * Gaddr loads up a register with an address of an external item.
214 * Gstack is the number of bytes that Gpush pushes on the stack.
215 *
216 * Varients of the above with E or L prefixes do EXT(name) or LCL(name)
217 * respectively.
218 */
219
220#ifndef __SHARED__
221#define Gpush
222#define Gpop
223#define Gload
224#define Gcall(func)		call func
225#define Gotoff(lab)		lab
226#define Gotoff2(l,r)		l(r)
227#define Gotoff3(l,r,s)		l(,r,s)
228#define Gaddr(to,lab)		movl $lab,to
229#define Gcmp(lab,reg)		cmpl $lab,reg
230#define Gmemload(lab,reg)	movl lab,reg
231#define Gmemstore(reg,lab,tmp)	movl reg,lab
232#define Gstack			0
233
234#else
235#ifdef __ELF__			/* ELF shared libraries */
236#define Gpush			pushl %ebx
237#define Gpop			popl %ebx
238#define Gload			call 9f; 9: popl %ebx; addl $_GLOBAL_OFFSET_TABLE_+[.-9b],%ebx
239#define Gcall(func)		call EXT(func)@PLT
240#define Gotoff(lab)		lab@GOTOFF(%ebx)
241#define Gotoff2(l,r)		l@GOTOFF(%ebx,r)
242#define Gotoff3(l,r,s)		l@GOTOFF(%ebx,r,s)
243#define Gaddr(to,lab)		movl lab@GOT(%ebx),to
244#define Gcmp(lab,reg)		cmpl reg,lab@GOT(%ebx)
245#define Gmemload(lab,reg)	movl lab@GOT(%ebx),reg; movl (reg),reg
246#define Gmemstore(reg,lab,tmp)	movl lab@GOT(%ebx),tmp; movl reg,(tmp)
247#define Gstack			4
248
249#else				/* ROSE shared libraries */
250#define Gpush
251#define Gpop
252#define Gload
253#define Gcall(func)		call *9f; .data; .align ALIGN; 9: .long func; .text
254#define Gotoff(lab)		lab
255#define Gotoff2(l,r)		l(r)
256#define Gotoff3(l,r,s)		l(,r,s)
257#define Gaddr(to,lab)		movl 9f,to; .data; .align ALIGN; 9: .long lab; .text
258#define Gcmp(lab,reg)		cmpl reg,9f; .data; .align ALIGN; 9: .long lab; .text
259#define Gmemload(lab,reg)	movl 9f,reg; movl (reg),reg; .data; .align ALIGN; 9: .long lab; .text
260#define Gmemstore(reg,lab,tmp)	movl 9f,tmp; movl reg,(tmp); .data; .align ALIGN; 9: .long lab; .text
261#define Gstack			0
262#endif	/* __ELF__ */
263#endif	/* __SHARED__ */
264
265/* Egotoff is not provided, since external symbols should not use @GOTOFF
266   relocations.  */
267#define Egcall(func)		Gcall(EXT(func))
268#define Egaddr(to,lab)		Gaddr(to,EXT(lab))
269#define Egcmp(lab,reg)		Gcmp(EXT(lab),reg)
270#define Egmemload(lab,reg)	Gmemload(EXT(lab),reg)
271#define Egmemstore(reg,lab,tmp)	Gmemstore(reg,EXT(lab),tmp)
272
273#define Lgotoff(lab)		Gotoff(LCL(lab))
274#define Lgotoff2(l,r)		Gotoff2(LCL(l),r)
275#define Lgotoff3(l,r,s)		Gotoff3(LCL(l),r,s)
276#define Lgcmp(lab,reg)		Gcmp(LCL(lab),reg)
277#define Lgmemload(lab,reg)	movl Lgotoff(lab),reg
278#define Lgmemstore(reg,lab,tmp)	movl reg,Lgotoff(lab)
279
280#ifndef ASSEMBLER
281/* These defines are here for .c files that wish to reference global symbols
282 * within __asm__ statements.
283 */
284#ifndef __NO_UNDERSCORES__
285#define CC_SYM_PREFIX "_"
286#else
287#define CC_SYM_PREFIX ""
288#endif /* __NO_UNDERSCORES__ */
289#endif /* ASSEMBLER */
290
291/*
292 * The following macros make calls into C code.
293 * They dynamically align the stack to 16 bytes.
294 */
295#if defined(__i386__)
296/*
297 * Arguments are moved (not pushed) onto the correctly aligned stack.
298 * NOTE: ESI is destroyed in the process, and hence cannot
299 * be directly used as a parameter. Users of this macro must
300 * independently preserve ESI (a non-volatile) if the routine is
301 * intended to be called from C, for instance.
302 */
303
304#define CCALL(fn)			\
305	movl	%esp, %esi		;\
306	andl	$0xFFFFFFF0, %esp	;\
307	call	EXT(fn)			;\
308	movl	%esi, %esp
309
310#define CCALL1(fn, arg1)		\
311	movl	%esp, %esi		;\
312	subl	$4, %esp		;\
313	andl	$0xFFFFFFF0, %esp	;\
314	movl	arg1, (%esp)		;\
315	call	EXT(fn)			;\
316	movl	%esi, %esp
317
318#define CCALL2(fn, arg1, arg2)		\
319	movl	%esp, %esi		;\
320	subl	$8, %esp		;\
321	andl	$0xFFFFFFF0, %esp	;\
322	movl	arg2, 4(%esp)		;\
323	movl	arg1, (%esp)		;\
324	call	EXT(fn)			;\
325	movl	%esi, %esp
326
327/* This variant exists to permit adjustment of the stack by "dtrace" */
328#define CCALL1WITHSP(fn, arg1)		\
329	movl	%esp, %esi		;\
330	subl	$12, %esp		;\
331	andl	$0xFFFFFFF0, %esp	;\
332	movl	%esi, 8(%esp)		;\
333	leal	8(%esp), %esi		;\
334	movl	%esi, 4(%esp)		;\
335	movl	arg1, (%esp)		;\
336	call	EXT(fn)			;\
337	movl	8(%esp), %esp
338
339/*
340 * CCALL5 is used for callee functions with 3 arguments but
341 * where arg2 (a3:a2) and arg3 (a5:a4) are 64-bit values.
342 */
343#define CCALL5(fn, a1, a2, a3, a4, a5)	\
344	movl	%esp, %esi		;\
345	subl	$20, %esp		;\
346	andl	$0xFFFFFFF0, %esp	;\
347	movl	a5, 16(%esp)		;\
348	movl	a4, 12(%esp)		;\
349	movl	a3,  8(%esp)		;\
350	movl	a2,  4(%esp)		;\
351	movl	a1,  (%esp)		;\
352	call	EXT(fn)			;\
353	movl	%esi, %esp
354
355#elif defined(__x86_64__)
356
357/* This variant exists to permit adjustment of the stack by "dtrace" */
358#define CCALLWITHSP(fn)				 \
359	mov	%rsp, %r12			;\
360	sub	$8, %rsp			;\
361	and	$0xFFFFFFFFFFFFFFF0, %rsp	;\
362	mov	%r12, (%rsp)			;\
363	leaq	(%rsp), %rsi			;\
364	call	EXT(fn)				;\
365	mov	(%rsp), %rsp
366
367#define CCALL(fn)				 \
368	mov	%rsp, %r12			;\
369	and	$0xFFFFFFFFFFFFFFF0, %rsp	;\
370	call	EXT(fn)				;\
371	mov	%r12, %rsp
372
373#define CCALL1(fn, arg1) 			 \
374	mov	arg1, %rdi 			;\
375	CCALL(fn)
376
377#define CCALL2(fn, arg1, arg2)		 	 \
378	mov	arg1, %rdi 			;\
379	mov	arg2, %rsi 			;\
380	CCALL(fn)
381
382#define CCALL3(fn, arg1, arg2, arg3) 		 \
383	mov	arg1, %rdi 			;\
384	mov	arg2, %rsi 			;\
385	mov	arg3, %rdx 			;\
386	CCALL(fn)
387
388#else
389#error unsupported architecture
390#endif
391
392#endif /* _I386_ASM_H_ */
393