gems-kernel/source/THIRDPARTY/xnu/EXTERNAL_HEADERS/architecture/i386/asm_help.h
2024-06-03 11:29:39 -05:00

413 lines
9.7 KiB
C

/*
* Copyright (c) 2021 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved.
*
* File: architecture/i386/asm_help.h
* Author: Mike DeMoney, NeXT Computer, Inc.
* Modified for i386 by: Bruce Martin, NeXT Computer, Inc.
*
* This header file defines macros useful when writing assembly code
* for the Intel i386 family processors.
*
* HISTORY
* 10-Mar-92 Bruce Martin (bmartin@next.com)
* Adapted to i386
* 23-Jan-91 Mike DeMoney (mike@next.com)
* Created.
*/
#ifndef _ARCH_I386_ASM_HELP_H_
#define _ARCH_I386_ASM_HELP_H_
#include <architecture/i386/reg_help.h>
#ifdef __ASSEMBLER__
/* Unwind Prologue added to each function to indicate the start of the unwind information. */
#define UNWIND_PROLOGUE \
.cfi_sections .eh_frame ;\
.cfi_startproc ;
/* Unwind Epilogue added to each function to indicate the end of the unwind information */
#define UNWIND_EPILOGUE .cfi_endproc
#define ALIGN \
.align 2, 0x90
#define ROUND_TO_STACK(len) \
(((len) + STACK_INCR - 1) / STACK_INCR * STACK_INCR)
#ifdef notdef
#if defined(__i386__)
#define CALL_MCOUNT \
pushl %ebp ;\
movl %esp, %ebp ;\
.data ;\
1: .long 0 ;\
.text ;\
lea 9b,%edx ;\
call mcount ;\
popl %ebp ;
#elif defined(__x86_64__)
#define CALL_MCOUNT \
pushq %rbp ;\
movq %rsp, %rbp ;\
.data ;\
1: .quad 0 ;\
.text ;\
lea 9b,%r13 ;\
call mcount ;\
popq %rbp ;
#endif
#else
#define CALL_MCOUNT
#endif
/*
* Prologue for functions that may call other functions. Saves
* registers and sets up a C frame.
*/
#if defined(__i386__)
#define NESTED_FUNCTION_PROLOGUE(localvarsize) \
.set L__framesize,ROUND_TO_STACK(localvarsize) ;\
.set L__nested_function, 1 ;\
CALL_MCOUNT \
.if L__framesize ;\
pushl %ebp ;\
movl %esp, %ebp ;\
subl $L__framesize, %esp ;\
.endif ;\
pushl %edi ;\
pushl %esi ;\
pushl %ebx
#elif defined(__x86_64__)
#define NESTED_FUNCTION_PROLOGUE(localvarsize) \
UNWIND_PROLOGUE ;\
.set L__framesize,ROUND_TO_STACK(localvarsize) ;\
.set L__nested_function, 1 ;\
CALL_MCOUNT \
.if L__framesize ;\
pushq %rbp ;\
movq %rsp, %rbp ;\
subq $L__framesize, %rsp ;\
.endif ;
#endif
/*
* Prologue for functions that do not call other functions. Does not
* save registers (this is the functions responsibility). Does set
* up a C frame.
*/
#if defined(__i386__)
#define LEAF_FUNCTION_PROLOGUE(localvarsize) \
.set L__framesize,ROUND_TO_STACK(localvarsize) ;\
.set L__nested_function, 0 ;\
CALL_MCOUNT \
.if L__framesize ;\
pushl %ebp ;\
movl %esp, %ebp ;\
subl $L__framesize, %esp ;\
.endif
#elif defined(__x86_64__)
#define LEAF_FUNCTION_PROLOGUE(localvarsize) \
UNWIND_PROLOGUE ;\
.set L__framesize,ROUND_TO_STACK(localvarsize) ;\
.set L__nested_function, 0 ;\
CALL_MCOUNT \
.if L__framesize ;\
pushq %rbp ;\
movq %rsp, %rbp ;\
subq $L__framesize, %rsp ;\
.endif
#endif
/*
* Epilogue for any function.
*
* We assume that all Leaf functions will be responsible for saving any
* local registers they clobber.
*/
#if defined(__i386__)
#define FUNCTION_EPILOGUE \
.if L__nested_function ;\
popl %ebx ;\
popl %esi ;\
popl %edi ;\
.endif ;\
.if L__framesize ;\
movl %ebp, %esp ;\
popl %ebp ;\
.endif ;\
ret
#elif defined(__x86_64__)
#define FUNCTION_EPILOGUE \
.if L__framesize ;\
movq %rbp, %rsp ;\
popq %rbp ;\
.endif ;\
ret ;\
UNWIND_EPILOGUE
#endif
/*
* Macros for declaring procedures
*
* Use of these macros allows ctags to have a predictable way
* to find various types of declarations. They also simplify
* inserting appropriate symbol table information.
*
* NOTE: these simple stubs will be replaced with more
* complicated versions once we know what the linker and gdb
* will require as far as register use masks and frame declarations.
* These macros may also be ifdef'ed in the future to contain profiling
* code.
*
*/
/*
* TEXT -- declare start of text segment
*/
#define TEXT \
.text
/*
* DATA -- declare start of data segment
*/
#define DATA \
.data
/*
* LEAF -- declare global leaf procedure
* NOTE: Control SHOULD NOT FLOW into a LEAF! A LEAF should only
* be jumped to. (A leaf may do an align.) Use a LABEL() if you
* need control to flow into the label.
*/
#define LEAF(name, localvarsize) \
.globl name ;\
ALIGN ;\
name: ;\
LEAF_FUNCTION_PROLOGUE(localvarsize)
/*
* X_LEAF -- declare alternate global label for leaf
*/
#define X_LEAF(name, value) \
.globl name ;\
.set name,value
/*
* P_LEAF -- declare private leaf procedure
*/
#define P_LEAF(name, localvarsize) \
ALIGN ;\
name: ;\
LEAF_FUNCTION_PROLOGUE(localvarsize)
/*
* LABEL -- declare a global code label
* MUST be used (rather than LEAF, NESTED, etc) if control
* "flows into" the label.
*/
#define LABEL(name) \
.globl name ;\
name:
/*
* NESTED -- declare procedure that invokes other procedures
*/
#define NESTED(name, localvarsize) \
.globl name ;\
ALIGN ;\
name: ;\
NESTED_FUNCTION_PROLOGUE(localvarsize)
/*
* X_NESTED -- declare alternate global label for nested proc
*/
#define X_NESTED(name, value) \
.globl name ;\
.set name,value
/*
* P_NESTED -- declare private nested procedure
*/
#define P_NESTED(name, localvarsize) \
ALIGN ;\
name: ;\
NESTED_FUNCTION_PROLOGUE(localvarsize)
/*
* END -- mark end of procedure
*/
#define END(name) \
FUNCTION_EPILOGUE
/*
* Storage definition macros
* The main purpose of these is to allow an easy handle for ctags
*/
/*
* IMPORT -- import symbol
*/
#define IMPORT(name) \
.reference name
/*
* ABS -- declare global absolute symbol
*/
#define ABS(name, value) \
.globl name ;\
.set name,value
/*
* P_ABS -- declare private absolute symbol
*/
#define P_ABS(name, value) \
.set name,value
/*
* EXPORT -- declare global label for data
*/
#define EXPORT(name) \
.globl name ;\
name:
/*
* BSS -- declare global zero'ed storage
*/
#define BSS(name,size) \
.comm name,size
/*
* P_BSS -- declare private zero'ed storage
*/
#define P_BSS(name,size) \
.lcomm name,size
/*
* dynamic/PIC macros for routines which reference external symbols
*/
#if defined(__DYNAMIC__)
#if defined(__i386__)
#define PICIFY(var) \
call 1f ; \
1: ; \
popl %edx ; \
movl L ## var ## __non_lazy_ptr-1b(%edx),%edx
#elif defined(__x86_64__)
#define PICIFY(var) \
movq var@GOTPCREL(%rip),%r11
#endif
#if defined(__i386__)
#define CALL_EXTERN_AGAIN(func) \
PICIFY(func) ; \
call *%edx
#elif defined(__x86_64__)
#define CALL_EXTERN_AGAIN(func) \
call func
#endif
#if defined(__i386__)
#define NON_LAZY_STUB(var) \
.section __IMPORT,__pointers,non_lazy_symbol_pointers ; \
L ## var ## __non_lazy_ptr: ; \
.indirect_symbol var ; \
.long 0 ; \
.text
#elif defined(__x86_64__)
#define NON_LAZY_STUB(var)
#endif
#define CALL_EXTERN(func) \
CALL_EXTERN_AGAIN(func) ; \
NON_LAZY_STUB(func)
#if defined(__i386__)
#define BRANCH_EXTERN(func) \
PICIFY(func) ; \
jmp *%edx ; \
NON_LAZY_STUB(func)
#elif defined(__x86_64__)
#define BRANCH_EXTERN(func) \
jmp func
#endif
#if defined(__i386__)
#define PUSH_EXTERN(var) \
PICIFY(var) ; \
movl (%edx),%edx ; \
pushl %edx ; \
NON_LAZY_STUB(var)
#endif
#if defined(__i386__)
#define REG_TO_EXTERN(reg, var) \
PICIFY(var) ; \
movl reg, (%edx) ; \
NON_LAZY_STUB(var)
#elif defined(__x86_64__)
#define REG_TO_EXTERN(reg, var) \
PICIFY(var) ; \
mov reg, (%r11)
#endif
#if defined(__i386__)
#define EXTERN_TO_REG(var, reg) \
call 1f ; \
1: ; \
popl %edx ; \
movl L ## var ##__non_lazy_ptr-1b(%edx),reg ; \
NON_LAZY_STUB(var)
#elif defined(__x86_64__)
#define EXTERN_TO_REG(var, reg) \
PICIFY(var) ; \
mov (%r11), reg
#endif
#else
#define BRANCH_EXTERN(func) jmp func
#define PUSH_EXTERN(var) push var
#define CALL_EXTERN(func) call func
#define CALL_EXTERN_AGAIN(func) call func
#if defined(__i386__)
#define REG_TO_EXTERN(reg, var) mov reg, var
#define EXTERN_TO_REG(var, reg) mov $ ## var, reg
#elif defined(__x86_64__)
#define REG_TO_EXTERN(reg, var) mov reg, var ## (%rip)
#define EXTERN_TO_REG(var, reg) mov var ## (%rip), reg
#endif
#endif
#endif /* __ASSEMBLER__ */
#endif /* _ARCH_I386_ASM_HELP_H_ */