1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/* Copyright (c) 1991 NeXT Computer, Inc.  All rights reserved.
24 *
25 *	File:	architecture/i386/asm_help.h
26 *	Author:	Mike DeMoney, NeXT Computer, Inc.
27 *	Modified for i386 by: Bruce Martin, NeXT Computer, Inc.
28 *
29 *	This header file defines macros useful when writing assembly code
30 *	for the Intel i386 family processors.
31 *
32 * HISTORY
33 * 10-Mar-92  Bruce Martin (bmartin@next.com)
34 *	Adapted to i386
35 * 23-Jan-91  Mike DeMoney (mike@next.com)
36 *	Created.
37 */
38
39#ifndef	_ARCH_I386_ASM_HELP_H_
40#define	_ARCH_I386_ASM_HELP_H_
41
42#include	<architecture/i386/reg_help.h>
43
44
45#ifdef	__ASSEMBLER__
46
47#define ALIGN						\
48	.align	2, 0x90
49
50#define	ROUND_TO_STACK(len)				\
51	(((len) + STACK_INCR - 1) / STACK_INCR * STACK_INCR)
52
53#ifdef notdef
54#if defined(__i386__)
55#define CALL_MCOUNT						\
56	pushl	%ebp						;\
57	movl	%esp, %ebp					;\
58	.data							;\
59	1: .long 0						;\
60	.text							;\
61	lea 9b,%edx						;\
62	call mcount						;\
63	popl	%ebp						;
64#elif defined(__x86_64__)
65#define CALL_MCOUNT						\
66	pushq	%rbp						;\
67	movq	%rsp, %rbp					;\
68	.data							;\
69	1: .quad 0						;\
70	.text							;\
71	lea 9b,%r13						;\
72	call mcount						;\
73	popq	%rbp					;
74#endif
75#else
76#define CALL_MCOUNT
77#endif
78
79/*
80 * Prologue for functions that may call other functions.  Saves
81 * registers and sets up a C frame.
82 */
83#if defined(__i386__)
84#define NESTED_FUNCTION_PROLOGUE(localvarsize)			\
85	.set	L__framesize,ROUND_TO_STACK(localvarsize)	;\
86	.set	L__nested_function, 1				;\
87	CALL_MCOUNT						\
88	.if L__framesize						;\
89	  pushl	%ebp						;\
90	  movl	%esp, %ebp					;\
91	  subl	$L__framesize, %esp				;\
92	.endif							;\
93	pushl	%edi						;\
94	pushl	%esi						;\
95	pushl	%ebx
96#elif defined(__x86_64__)
97#define NESTED_FUNCTION_PROLOGUE(localvarsize)			\
98	.set	L__framesize,ROUND_TO_STACK(localvarsize)	;\
99	.set	L__nested_function, 1				;\
100	CALL_MCOUNT						\
101	.if L__framesize						;\
102	  pushq	%rbp						;\
103	  movq	%rsp, %rbp					;\
104	  subq	$L__framesize, %rsp				;\
105	.endif							;
106#endif
107
108/*
109 * Prologue for functions that do not call other functions.  Does not
110 * save registers (this is the functions responsibility).  Does set
111 * up a C frame.
112 */
113#if defined(__i386__)
114#define LEAF_FUNCTION_PROLOGUE(localvarsize)			\
115	.set	L__framesize,ROUND_TO_STACK(localvarsize)	;\
116	.set	L__nested_function, 0				;\
117	CALL_MCOUNT						\
118	.if L__framesize						;\
119	  pushl	%ebp						;\
120	  movl	%esp, %ebp					;\
121	  subl	$L__framesize, %esp				;\
122	.endif
123#elif defined(__x86_64__)
124#define LEAF_FUNCTION_PROLOGUE(localvarsize)			\
125	.set	L__framesize,ROUND_TO_STACK(localvarsize)	;\
126	.set	L__nested_function, 0				;\
127	CALL_MCOUNT						\
128	.if L__framesize						;\
129	  pushq	%rbp						;\
130	  movq	%rsp, %rbp					;\
131	  subq	$L__framesize, %rsp				;\
132	.endif
133#endif
134
135/*
136 * Epilogue for any function.
137 *
138 * We assume that all Leaf functions will be responsible for saving any
139 * local registers they clobber.
140 */
141#if defined(__i386__)
142#define FUNCTION_EPILOGUE					\
143	.if L__nested_function					;\
144	  popl	%ebx						;\
145	  popl	%esi						;\
146	  popl	%edi						;\
147	.endif							;\
148	.if L__framesize						;\
149	  movl	%ebp, %esp					;\
150	  popl	%ebp						;\
151	.endif							;\
152	ret
153#elif defined(__x86_64__)
154#define FUNCTION_EPILOGUE					\
155	.if L__framesize						;\
156	  movq	%rbp, %rsp					;\
157	  popq	%rbp						;\
158	.endif							;\
159	ret
160#endif
161
162/*
163 * Macros for declaring procedures
164 *
165 * Use of these macros allows ctags to have a predictable way
166 * to find various types of declarations.  They also simplify
167 * inserting appropriate symbol table information.
168 *
169 * NOTE: these simple stubs will be replaced with more
170 * complicated versions once we know what the linker and gdb
171 * will require as far as register use masks and frame declarations.
172 * These macros may also be ifdef'ed in the future to contain profiling
173 * code.
174 *
175 */
176
177/*
178 * TEXT -- declare start of text segment
179 */
180#define	TEXT						\
181	.text
182
183/*
184 * DATA -- declare start of data segment
185 */
186#define DATA						\
187	.data
188
189/*
190 * LEAF -- declare global leaf procedure
191 * NOTE: Control SHOULD NOT FLOW into a LEAF!  A LEAF should only
192 * be jumped to.  (A leaf may do an align.)  Use a LABEL() if you
193 * need control to flow into the label.
194 */
195#define	LEAF(name, localvarsize)			\
196	.globl	name					;\
197	ALIGN						;\
198name:							;\
199	LEAF_FUNCTION_PROLOGUE(localvarsize)
200
201/*
202 * X_LEAF -- declare alternate global label for leaf
203 */
204#define	X_LEAF(name, value)				\
205	.globl	name					;\
206	.set	name,value
207
208/*
209 * P_LEAF -- declare private leaf procedure
210 */
211#define	P_LEAF(name, localvarsize)			\
212	ALIGN						;\
213name:							;\
214	LEAF_FUNCTION_PROLOGUE(localvarsize)
215
216/*
217 * LABEL -- declare a global code label
218 * MUST be used (rather than LEAF, NESTED, etc) if control
219 * "flows into" the label.
220 */
221#define	LABEL(name)					\
222	.globl	name					;\
223name:
224
225/*
226 * NESTED -- declare procedure that invokes other procedures
227 */
228#define	NESTED(name, localvarsize)			\
229	.globl	name					;\
230	ALIGN						;\
231name:							;\
232	NESTED_FUNCTION_PROLOGUE(localvarsize)
233
234/*
235 * X_NESTED -- declare alternate global label for nested proc
236 */
237#define	X_NESTED(name, value)				\
238	.globl	name					;\
239	.set	name,value
240
241/*
242 * P_NESTED -- declare private nested procedure
243 */
244#define	P_NESTED(name, localvarsize)			\
245	ALIGN						;\
246name:							;\
247	NESTED_FUNCTION_PROLOGUE(localvarsize)
248
249/*
250 * END -- mark end of procedure
251 */
252#define	END(name)					\
253	FUNCTION_EPILOGUE
254
255
256/*
257 * Storage definition macros
258 * The main purpose of these is to allow an easy handle for ctags
259 */
260
261/*
262 * IMPORT -- import symbol
263 */
264#define	IMPORT(name)					\
265	.reference	name
266
267/*
268 * ABS -- declare global absolute symbol
269 */
270#define	ABS(name, value)				\
271	.globl	name					;\
272	.set	name,value
273
274/*
275 * P_ABS -- declare private absolute symbol
276 */
277#define	P_ABS(name, value)				\
278	.set	name,value
279
280/*
281 * EXPORT -- declare global label for data
282 */
283#define	EXPORT(name)					\
284	.globl	name					;\
285name:
286
287/*
288 * BSS -- declare global zero'ed storage
289 */
290#define	BSS(name,size)					\
291	.comm	name,size
292
293
294/*
295 * P_BSS -- declare private zero'ed storage
296 */
297#define	P_BSS(name,size)				\
298	.lcomm	name,size
299
300/*
301 * dynamic/PIC macros for routines which reference external symbols
302 */
303
304#if defined(__DYNAMIC__)
305#if defined(__i386__)
306#define PICIFY(var)					\
307	call	1f					; \
3081:							; \
309	popl	%edx					; \
310	movl	L ## var ## __non_lazy_ptr-1b(%edx),%edx
311#elif defined(__x86_64__)
312#define PICIFY(var)					\
313	movq	var@GOTPCREL(%rip),%r11
314#endif
315
316#if defined(__i386__)
317#define CALL_EXTERN_AGAIN(func)	\
318	PICIFY(func)		; \
319	call	*%edx
320#elif defined(__x86_64__)
321#define CALL_EXTERN_AGAIN(func)	\
322	call	func
323#endif
324
325#if defined(__i386__)
326#define NON_LAZY_STUB(var)	\
327.section __IMPORT,__pointers,non_lazy_symbol_pointers	; \
328L ## var ## __non_lazy_ptr:	; \
329.indirect_symbol var		; \
330.long 0				; \
331.text
332#elif defined(__x86_64__)
333#define NON_LAZY_STUB(var)
334#endif
335
336#define CALL_EXTERN(func)	\
337	CALL_EXTERN_AGAIN(func)	; \
338	NON_LAZY_STUB(func)
339
340#if defined(__i386__)
341#define BRANCH_EXTERN(func)	\
342	PICIFY(func)		; \
343	jmp	*%edx		; \
344	NON_LAZY_STUB(func)
345#elif defined(__x86_64__)
346#define BRANCH_EXTERN(func)	\
347	jmp	func
348#endif
349
350#if defined(__i386__)
351#define PUSH_EXTERN(var)	\
352	PICIFY(var)		; \
353	movl	(%edx),%edx	; \
354	pushl	%edx		; \
355	NON_LAZY_STUB(var)
356#endif
357
358#if defined(__i386__)
359#define REG_TO_EXTERN(reg, var)	\
360	PICIFY(var)		; \
361	movl	reg, (%edx)	; \
362	NON_LAZY_STUB(var)
363#elif defined(__x86_64__)
364#define REG_TO_EXTERN(reg, var)	\
365	PICIFY(var)		; \
366	mov		reg, (%r11)
367#endif
368
369#if defined(__i386__)
370#define EXTERN_TO_REG(var, reg)				\
371	call	1f					; \
3721:							; \
373	popl	%edx					; \
374	movl	L ## var ##__non_lazy_ptr-1b(%edx),reg	; \
375	NON_LAZY_STUB(var)
376#elif defined(__x86_64__)
377#define EXTERN_TO_REG(var, reg)				\
378	PICIFY(var)		; \
379	mov    (%r11), reg
380#endif
381
382#else
383#define BRANCH_EXTERN(func)	jmp	func
384#define PUSH_EXTERN(var)	push	var
385#define CALL_EXTERN(func)	call	func
386#define CALL_EXTERN_AGAIN(func)	call	func
387#if defined(__i386__)
388#define REG_TO_EXTERN(reg, var)	mov	reg, var
389#define EXTERN_TO_REG(var, reg)	mov	$ ## var, reg
390#elif defined(__x86_64__)
391#define REG_TO_EXTERN(reg, var)	mov	reg, var ## (%rip)
392#define EXTERN_TO_REG(var, reg)	mov	var ## (%rip), reg
393#endif
394#endif
395
396#endif	/* __ASSEMBLER__ */
397
398#endif	/* _ARCH_I386_ASM_HELP_H_ */
399