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