mirror of
https://git.planet-casio.com/Lephenixnoir/OpenLibm.git
synced 2024-12-29 13:03:42 +01:00
409 lines
11 KiB
C
409 lines
11 KiB
C
|
/*
|
||
|
* Copyright (c) 2000 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@
|
||
|
*/
|
||
|
/*
|
||
|
* @OSF_COPYRIGHT@
|
||
|
*/
|
||
|
/*
|
||
|
* Mach Operating System
|
||
|
* Copyright (c) 1991,1990,1989 Carnegie Mellon University
|
||
|
* All Rights Reserved.
|
||
|
*
|
||
|
* Permission to use, copy, modify and distribute this software and its
|
||
|
* documentation is hereby granted, provided that both the copyright
|
||
|
* notice and this permission notice appear in all copies of the
|
||
|
* software, derivative works or modified versions, and any portions
|
||
|
* thereof, and that both notices appear in supporting documentation.
|
||
|
*
|
||
|
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
|
||
|
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
|
||
|
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
|
||
|
*
|
||
|
* Carnegie Mellon requests users of this software to return to
|
||
|
*
|
||
|
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
|
||
|
* School of Computer Science
|
||
|
* Carnegie Mellon University
|
||
|
* Pittsburgh PA 15213-3890
|
||
|
*
|
||
|
* any improvements or extensions that they make and grant Carnegie Mellon
|
||
|
* the rights to redistribute these changes.
|
||
|
*/
|
||
|
|
||
|
#ifndef _I386_ASM_H_
|
||
|
#define _I386_ASM_H_
|
||
|
|
||
|
#ifdef _KERNEL
|
||
|
#include <gprof.h>
|
||
|
#endif /* _KERNEL */
|
||
|
|
||
|
#ifdef MACH_KERNEL
|
||
|
#include <mach_kdb.h>
|
||
|
#else /* !MACH_KERNEL */
|
||
|
#define MACH_KDB 0
|
||
|
#endif /* !MACH_KERNEL */
|
||
|
|
||
|
|
||
|
#if defined(MACH_KERNEL) || defined(_KERNEL)
|
||
|
#include <gprof.h>
|
||
|
#endif /* MACH_KERNEL || _KERNEL */
|
||
|
|
||
|
#if defined(__i386__)
|
||
|
|
||
|
#define S_PC (%esp)
|
||
|
#define S_ARG0 4(%esp)
|
||
|
#define S_ARG1 8(%esp)
|
||
|
#define S_ARG2 12(%esp)
|
||
|
#define S_ARG3 16(%esp)
|
||
|
#define S_ARG4 20(%esp)
|
||
|
|
||
|
#define FRAME pushl %ebp; movl %esp, %ebp
|
||
|
#define EMARF leave
|
||
|
|
||
|
#define B_LINK (%ebp)
|
||
|
#define B_PC 4(%ebp)
|
||
|
#define B_ARG0 8(%ebp)
|
||
|
#define B_ARG1 12(%ebp)
|
||
|
#define B_ARG2 16(%ebp)
|
||
|
#define B_ARG3 20(%ebp)
|
||
|
|
||
|
#elif defined(__x86_64__)
|
||
|
|
||
|
#define S_PC (%rsp)
|
||
|
|
||
|
#define FRAME pushq %rbp; movq %rsp, %rbp
|
||
|
#define EMARF leave
|
||
|
|
||
|
#define B_LINK (%rbp)
|
||
|
#define B_PC 8(%rbp)
|
||
|
|
||
|
#else
|
||
|
#error unsupported architecture
|
||
|
#endif
|
||
|
|
||
|
/* There is another definition of ALIGN for .c sources */
|
||
|
#ifdef ASSEMBLER
|
||
|
#define ALIGN 4,0x90
|
||
|
#endif /* ASSEMBLER */
|
||
|
|
||
|
#ifndef FALIGN
|
||
|
#define FALIGN ALIGN
|
||
|
#endif
|
||
|
|
||
|
#define LB(x,n) n
|
||
|
#if __STDC__
|
||
|
#ifndef __NO_UNDERSCORES__
|
||
|
#define LCL(x) L ## x
|
||
|
#define EXT(x) _ ## x
|
||
|
#define LEXT(x) _ ## x ## :
|
||
|
#else
|
||
|
#define LCL(x) .L ## x
|
||
|
#define EXT(x) x
|
||
|
#define LEXT(x) x ## :
|
||
|
#endif
|
||
|
#define LBc(x,n) n ## :
|
||
|
#define LBb(x,n) n ## b
|
||
|
#define LBf(x,n) n ## f
|
||
|
#else /* __STDC__ */
|
||
|
#ifndef __NO_UNDERSCORES__
|
||
|
#define LCL(x) L/**/x
|
||
|
#define EXT(x) _/**/x
|
||
|
#define LEXT(x) _/**/x/**/:
|
||
|
#else /* __NO_UNDERSCORES__ */
|
||
|
#define LCL(x) .L/**/x
|
||
|
#define EXT(x) x
|
||
|
#define LEXT(x) x/**/:
|
||
|
#endif /* __NO_UNDERSCORES__ */
|
||
|
#define LBc(x,n) n/**/:
|
||
|
#define LBb(x,n) n/**/b
|
||
|
#define LBf(x,n) n/**/f
|
||
|
#endif /* __STDC__ */
|
||
|
|
||
|
#define SVC .byte 0x9a; .long 0; .word 0x7
|
||
|
|
||
|
#define RPC_SVC .byte 0x9a; .long 0; .word 0xf
|
||
|
|
||
|
#define String .asciz
|
||
|
#define Value .word
|
||
|
#define Times(a,b) (a*b)
|
||
|
#define Divide(a,b) (a/b)
|
||
|
|
||
|
#define INB inb %dx, %al
|
||
|
#define OUTB outb %al, %dx
|
||
|
#define INL inl %dx, %eax
|
||
|
#define OUTL outl %eax, %dx
|
||
|
|
||
|
#define data16 .byte 0x66
|
||
|
#define addr16 .byte 0x67
|
||
|
|
||
|
#if !GPROF
|
||
|
#define MCOUNT
|
||
|
|
||
|
#elif defined(__SHARED__)
|
||
|
#define MCOUNT ; .data;\
|
||
|
.align ALIGN;\
|
||
|
LBc(x, 8) .long 0;\
|
||
|
.text;\
|
||
|
Gpush;\
|
||
|
Gload;\
|
||
|
leal Gotoff(LBb(x,8)),%edx;\
|
||
|
Egaddr(%eax,_mcount_ptr);\
|
||
|
Gpop;\
|
||
|
call *(%eax);
|
||
|
|
||
|
#else /* !GPROF, !__SHARED__ */
|
||
|
#define MCOUNT ; call mcount;
|
||
|
#endif /* GPROF */
|
||
|
|
||
|
#ifdef __ELF__
|
||
|
#define ELF_FUNC(x) .type x,@function
|
||
|
#define ELF_DATA(x) .type x,@object
|
||
|
#define ELF_SIZE(x,s) .size x,s
|
||
|
#else
|
||
|
#define ELF_FUNC(x)
|
||
|
#define ELF_DATA(x)
|
||
|
#define ELF_SIZE(x,s)
|
||
|
#endif
|
||
|
|
||
|
#define Entry(x) .globl EXT(x); ELF_FUNC(EXT(x)); .align FALIGN; LEXT(x)
|
||
|
#define ENTRY(x) Entry(x) MCOUNT
|
||
|
#define ENTRY2(x,y) .globl EXT(x); .globl EXT(y); \
|
||
|
ELF_FUNC(EXT(x)); ELF_FUNC(EXT(y)); \
|
||
|
.align FALIGN; LEXT(x); LEXT(y) \
|
||
|
MCOUNT
|
||
|
#if __STDC__
|
||
|
#define ASENTRY(x) .globl x; .align FALIGN; x ## : ELF_FUNC(x) MCOUNT
|
||
|
#else
|
||
|
#define ASENTRY(x) .globl x; .align FALIGN; x: ELF_FUNC(x) MCOUNT
|
||
|
#endif /* __STDC__ */
|
||
|
|
||
|
#define DATA(x) .globl EXT(x); ELF_DATA(EXT(x)); .align ALIGN; LEXT(x)
|
||
|
|
||
|
#define End(x) ELF_SIZE(x,.-x)
|
||
|
#define END(x) End(EXT(x))
|
||
|
#define ENDDATA(x) END(x)
|
||
|
#define Enddata(x) End(x)
|
||
|
|
||
|
/*
|
||
|
* ELF shared library accessor macros.
|
||
|
* Gpush saves the %ebx register used for the GOT address
|
||
|
* Gpop pops %ebx if we need a GOT
|
||
|
* Gload loads %ebx with the GOT address if shared libraries are used
|
||
|
* Gcall calls an external function.
|
||
|
* Gotoff allows you to reference local labels.
|
||
|
* Gotoff2 allows you to reference local labels with an index reg.
|
||
|
* Gotoff3 allows you to reference local labels with an index reg & size.
|
||
|
* Gaddr loads up a register with an address of an external item.
|
||
|
* Gstack is the number of bytes that Gpush pushes on the stack.
|
||
|
*
|
||
|
* Varients of the above with E or L prefixes do EXT(name) or LCL(name)
|
||
|
* respectively.
|
||
|
*/
|
||
|
|
||
|
#ifndef __SHARED__
|
||
|
#define Gpush
|
||
|
#define Gpop
|
||
|
#define Gload
|
||
|
#define Gcall(func) call func
|
||
|
#define Gotoff(lab) lab
|
||
|
#define Gotoff2(l,r) l(r)
|
||
|
#define Gotoff3(l,r,s) l(,r,s)
|
||
|
#define Gaddr(to,lab) movl $lab,to
|
||
|
#define Gcmp(lab,reg) cmpl $lab,reg
|
||
|
#define Gmemload(lab,reg) movl lab,reg
|
||
|
#define Gmemstore(reg,lab,tmp) movl reg,lab
|
||
|
#define Gstack 0
|
||
|
|
||
|
#else
|
||
|
#ifdef __ELF__ /* ELF shared libraries */
|
||
|
#define Gpush pushl %ebx
|
||
|
#define Gpop popl %ebx
|
||
|
#define Gload call 9f; 9: popl %ebx; addl $_GLOBAL_OFFSET_TABLE_+[.-9b],%ebx
|
||
|
#define Gcall(func) call EXT(func)@PLT
|
||
|
#define Gotoff(lab) lab@GOTOFF(%ebx)
|
||
|
#define Gotoff2(l,r) l@GOTOFF(%ebx,r)
|
||
|
#define Gotoff3(l,r,s) l@GOTOFF(%ebx,r,s)
|
||
|
#define Gaddr(to,lab) movl lab@GOT(%ebx),to
|
||
|
#define Gcmp(lab,reg) cmpl reg,lab@GOT(%ebx)
|
||
|
#define Gmemload(lab,reg) movl lab@GOT(%ebx),reg; movl (reg),reg
|
||
|
#define Gmemstore(reg,lab,tmp) movl lab@GOT(%ebx),tmp; movl reg,(tmp)
|
||
|
#define Gstack 4
|
||
|
|
||
|
#else /* ROSE shared libraries */
|
||
|
#define Gpush
|
||
|
#define Gpop
|
||
|
#define Gload
|
||
|
#define Gcall(func) call *9f; .data; .align ALIGN; 9: .long func; .text
|
||
|
#define Gotoff(lab) lab
|
||
|
#define Gotoff2(l,r) l(r)
|
||
|
#define Gotoff3(l,r,s) l(,r,s)
|
||
|
#define Gaddr(to,lab) movl 9f,to; .data; .align ALIGN; 9: .long lab; .text
|
||
|
#define Gcmp(lab,reg) cmpl reg,9f; .data; .align ALIGN; 9: .long lab; .text
|
||
|
#define Gmemload(lab,reg) movl 9f,reg; movl (reg),reg; .data; .align ALIGN; 9: .long lab; .text
|
||
|
#define Gmemstore(reg,lab,tmp) movl 9f,tmp; movl reg,(tmp); .data; .align ALIGN; 9: .long lab; .text
|
||
|
#define Gstack 0
|
||
|
#endif /* __ELF__ */
|
||
|
#endif /* __SHARED__ */
|
||
|
|
||
|
/* Egotoff is not provided, since external symbols should not use @GOTOFF
|
||
|
relocations. */
|
||
|
#define Egcall(func) Gcall(EXT(func))
|
||
|
#define Egaddr(to,lab) Gaddr(to,EXT(lab))
|
||
|
#define Egcmp(lab,reg) Gcmp(EXT(lab),reg)
|
||
|
#define Egmemload(lab,reg) Gmemload(EXT(lab),reg)
|
||
|
#define Egmemstore(reg,lab,tmp) Gmemstore(reg,EXT(lab),tmp)
|
||
|
|
||
|
#define Lgotoff(lab) Gotoff(LCL(lab))
|
||
|
#define Lgotoff2(l,r) Gotoff2(LCL(l),r)
|
||
|
#define Lgotoff3(l,r,s) Gotoff3(LCL(l),r,s)
|
||
|
#define Lgcmp(lab,reg) Gcmp(LCL(lab),reg)
|
||
|
#define Lgmemload(lab,reg) movl Lgotoff(lab),reg
|
||
|
#define Lgmemstore(reg,lab,tmp) movl reg,Lgotoff(lab)
|
||
|
|
||
|
#ifdef ASSEMBLER
|
||
|
#if MACH_KDB
|
||
|
#include <ddb/stab.h>
|
||
|
/*
|
||
|
* This pseudo-assembler line is added so that there will be at least
|
||
|
* one N_SO entry in the symbol stable to define the current file name.
|
||
|
*/
|
||
|
#endif /* MACH_KDB */
|
||
|
|
||
|
#else /* NOT ASSEMBLER */
|
||
|
|
||
|
/* These defines are here for .c files that wish to reference global symbols
|
||
|
* within __asm__ statements.
|
||
|
*/
|
||
|
#ifndef __NO_UNDERSCORES__
|
||
|
#define CC_SYM_PREFIX "_"
|
||
|
#else
|
||
|
#define CC_SYM_PREFIX ""
|
||
|
#endif /* __NO_UNDERSCORES__ */
|
||
|
#endif /* ASSEMBLER */
|
||
|
|
||
|
/*
|
||
|
* The following macros make calls into C code.
|
||
|
* They dynamically align the stack to 16 bytes.
|
||
|
*/
|
||
|
#if defined(__i386__)
|
||
|
/*
|
||
|
* Arguments are moved (not pushed) onto the correctly aligned stack.
|
||
|
* NOTE: ESI is destroyed in the process, and hence cannot
|
||
|
* be directly used as a parameter. Users of this macro must
|
||
|
* independently preserve ESI (a non-volatile) if the routine is
|
||
|
* intended to be called from C, for instance.
|
||
|
*/
|
||
|
|
||
|
#define CCALL(fn) \
|
||
|
movl %esp, %esi ;\
|
||
|
andl $0xFFFFFFF0, %esp ;\
|
||
|
call EXT(fn) ;\
|
||
|
movl %esi, %esp
|
||
|
|
||
|
#define CCALL1(fn, arg1) \
|
||
|
movl %esp, %esi ;\
|
||
|
subl $4, %esp ;\
|
||
|
andl $0xFFFFFFF0, %esp ;\
|
||
|
movl arg1, (%esp) ;\
|
||
|
call EXT(fn) ;\
|
||
|
movl %esi, %esp
|
||
|
|
||
|
#define CCALL2(fn, arg1, arg2) \
|
||
|
movl %esp, %esi ;\
|
||
|
subl $8, %esp ;\
|
||
|
andl $0xFFFFFFF0, %esp ;\
|
||
|
movl arg2, 4(%esp) ;\
|
||
|
movl arg1, (%esp) ;\
|
||
|
call EXT(fn) ;\
|
||
|
movl %esi, %esp
|
||
|
|
||
|
/* This variant exists to permit adjustment of the stack by "dtrace" */
|
||
|
#define CCALL1WITHSP(fn, arg1) \
|
||
|
movl %esp, %esi ;\
|
||
|
subl $12, %esp ;\
|
||
|
andl $0xFFFFFFF0, %esp ;\
|
||
|
movl %esi, 8(%esp) ;\
|
||
|
leal 8(%esp), %esi ;\
|
||
|
movl %esi, 4(%esp) ;\
|
||
|
movl arg1, (%esp) ;\
|
||
|
call EXT(fn) ;\
|
||
|
movl 8(%esp), %esp
|
||
|
|
||
|
/*
|
||
|
* CCALL5 is used for callee functions with 3 arguments but
|
||
|
* where arg2 (a3:a2) and arg3 (a5:a4) are 64-bit values.
|
||
|
*/
|
||
|
#define CCALL5(fn, a1, a2, a3, a4, a5) \
|
||
|
movl %esp, %esi ;\
|
||
|
subl $20, %esp ;\
|
||
|
andl $0xFFFFFFF0, %esp ;\
|
||
|
movl a5, 16(%esp) ;\
|
||
|
movl a4, 12(%esp) ;\
|
||
|
movl a3, 8(%esp) ;\
|
||
|
movl a2, 4(%esp) ;\
|
||
|
movl a1, (%esp) ;\
|
||
|
call EXT(fn) ;\
|
||
|
movl %esi, %esp
|
||
|
|
||
|
#elif defined(__x86_64__)
|
||
|
|
||
|
/* This variant exists to permit adjustment of the stack by "dtrace" */
|
||
|
#define CCALLWITHSP(fn) \
|
||
|
mov %rsp, %r12 ;\
|
||
|
sub $8, %rsp ;\
|
||
|
and $0xFFFFFFFFFFFFFFF0, %rsp ;\
|
||
|
mov %r12, (%rsp) ;\
|
||
|
leaq (%rsp), %rsi ;\
|
||
|
call EXT(fn) ;\
|
||
|
mov (%rsp), %rsp
|
||
|
|
||
|
#define CCALL(fn) \
|
||
|
mov %rsp, %r12 ;\
|
||
|
and $0xFFFFFFFFFFFFFFF0, %rsp ;\
|
||
|
call EXT(fn) ;\
|
||
|
mov %r12, %rsp
|
||
|
|
||
|
#define CCALL1(fn, arg1) \
|
||
|
mov arg1, %rdi ;\
|
||
|
CCALL(fn)
|
||
|
|
||
|
#define CCALL2(fn, arg1, arg2) \
|
||
|
mov arg1, %rdi ;\
|
||
|
CCALL(fn)
|
||
|
|
||
|
#define CCALL3(fn, arg1, arg2, arg3) \
|
||
|
mov arg1, %rdi ;\
|
||
|
mov arg2, %rsi ;\
|
||
|
mov arg3, %rdx ;\
|
||
|
CCALL(fn)
|
||
|
|
||
|
#else
|
||
|
#error unsupported architecture
|
||
|
#endif
|
||
|
|
||
|
#endif /* _I386_ASM_H_ */
|