added 2 changesets to branch 'refs/remotes/xyzzy-github/x86_64' old head: e3ac2588e64059e0c140504e9acc8e73b3c36fdc new head: 3fde53501d6fd13daa168378d3f8ae8f3ca6bafd ---------------------------------------------------------------------------- 5f119ed: Added x86_64 glue code. 3fde535: Updated x86_64 fenv.h and added fenv.c. [ Alex Smith <alex@xxxxxxxxxxxxxxxx> ] ---------------------------------------------------------------------------- 8 files changed, 463 insertions(+), 7 deletions(-) headers/posix/arch/x86_64/fenv.h | 13 +- headers/posix/arch/x86_64/fpu.h | 218 ++++++++++++++++++++++ headers/posix/fenv.h | 2 +- src/system/glue/arch/x86_64/Jamfile | 7 + src/system/glue/arch/x86_64/crti.S | 43 +++++ src/system/glue/arch/x86_64/crtn.S | 27 +++ src/system/libroot/posix/arch/x86_64/Jamfile | 2 +- src/system/libroot/posix/arch/x86_64/fenv.c | 158 ++++++++++++++++ ############################################################################ Commit: 5f119ed78f400fbaec842d982fb7943a14d6b60e Author: Alex Smith <alex@xxxxxxxxxxxxxxxx> Date: Fri Jul 27 08:22:54 2012 UTC Added x86_64 glue code. ---------------------------------------------------------------------------- diff --git a/src/system/glue/arch/x86_64/Jamfile b/src/system/glue/arch/x86_64/Jamfile new file mode 100644 index 0000000..4d43342 --- /dev/null +++ b/src/system/glue/arch/x86_64/Jamfile @@ -0,0 +1,7 @@ +SubDir HAIKU_TOP src system glue arch x86_64 ; + +KernelObjects + crti.S + crtn.S + ; + diff --git a/src/system/glue/arch/x86_64/crti.S b/src/system/glue/arch/x86_64/crti.S new file mode 100644 index 0000000..3ef8e5f --- /dev/null +++ b/src/system/glue/arch/x86_64/crti.S @@ -0,0 +1,43 @@ +/* + * Copyright 2005-2006, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + * Copyright 2012, Alex Smith, alex@xxxxxxxxxxxxxxxxx + * Distributed under the terms of the MIT License. + */ + + +#include <asm_defs.h> + + +/** This file contains the first part of the ".init" and ".fini" sections in + * the ELF executable. + * The functions defined here will be called during initialization/termination + * of the loaded executable/library. The ".init" and ".fini" sections are + * stacked together like this: + * + * crti.S entry point + * call to _init_before/_term_before + * crtbegin.S GCC specific: constructors/destructors are called, ... + * crtend.S + * crtn.S call to _init_after/_term_after + * exit + */ + + +.section .init +FUNCTION(_init): + push %rbp + movq %rsp, %rbp + + // Preserve image ID for call to __haiku_init_after. + push %rdi + + call __haiku_init_before + // crtbegin.o stuff comes here + +.section .fini +FUNCTION(_fini): + push %rbp + movq %rsp, %rbp + push %rdi + call __haiku_term_before + // crtend.o stuff comes here diff --git a/src/system/glue/arch/x86_64/crtn.S b/src/system/glue/arch/x86_64/crtn.S new file mode 100644 index 0000000..8ed6433 --- /dev/null +++ b/src/system/glue/arch/x86_64/crtn.S @@ -0,0 +1,27 @@ +/* + * Copyright 2005-2006, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + * Copyright 2012, Alex Smith, alex@xxxxxxxxxxxxxxxxx + * Distributed under the terms of the MIT License. + */ + + +/** This file contains the final part of the ".init" and ".fini" sections in + * the ELF executable. It is tightly connected to crti.S. + * Have a look at crti.S to find a description of what happens here. + */ + + +.section .init + // The image ID is preserved on the stack. + pop %rdi + call __haiku_init_after + movq %rbp, %rsp + pop %rbp + ret + +.section .fini + pop %rdi + call __haiku_term_after + movq %rbp, %rsp + pop %rbp + ret ############################################################################ Commit: 3fde53501d6fd13daa168378d3f8ae8f3ca6bafd Author: Alex Smith <alex@xxxxxxxxxxxxxxxx> Date: Fri Jul 27 14:21:41 2012 UTC Updated x86_64 fenv.h and added fenv.c. ---------------------------------------------------------------------------- diff --git a/headers/posix/arch/x86_64/fenv.h b/headers/posix/arch/x86_64/fenv.h index a9992f9..9a3df8e 100644 --- a/headers/posix/arch/x86_64/fenv.h +++ b/headers/posix/arch/x86_64/fenv.h @@ -111,7 +111,8 @@ feclearexcept(int __excepts) static __inline int fegetexceptflag(fexcept_t *__flagp, int __excepts) { - int __mxcsr, __status; + uint32_t __mxcsr; + uint16_t __status; __stmxcsr(&__mxcsr); __fnstsw(&__status); @@ -125,7 +126,8 @@ int feraiseexcept(int __excepts); static __inline int fetestexcept(int __excepts) { - int __mxcsr, __status; + uint32_t __mxcsr; + uint16_t __status; __stmxcsr(&__mxcsr); __fnstsw(&__status); @@ -135,7 +137,7 @@ fetestexcept(int __excepts) static __inline int fegetround(void) { - int __control; + uint16_t __control; /* * We assume that the x87 and the SSE unit agree on the @@ -150,7 +152,8 @@ fegetround(void) static __inline int fesetround(int __round) { - int __mxcsr, __control; + uint32_t __mxcsr; + uint16_t __control; if (__round & ~_ROUND_MASK) return (-1); @@ -198,7 +201,7 @@ int fedisableexcept(int __mask); static __inline int fegetexcept(void) { - int __control; + uint16_t __control; /* * We assume that the masks for the x87 and the SSE unit are diff --git a/headers/posix/arch/x86_64/fpu.h b/headers/posix/arch/x86_64/fpu.h new file mode 100644 index 0000000..a22d8ca --- /dev/null +++ b/headers/posix/arch/x86_64/fpu.h @@ -0,0 +1,218 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)npx.h 5.3 (Berkeley) 1/18/91 + * $FreeBSD$ + */ + +/* + * Floating Point Data Structures and Constants + * W. Jolitz 1/90 + */ + +#ifndef _X86_FPU_H_ +#define _X86_FPU_H_ + +#define __aligned(x) __attribute__((__aligned__(x))) + +/* Environment information of floating point unit. */ +struct env87 { + int32_t en_cw; /* control word (16bits) */ + int32_t en_sw; /* status word (16bits) */ + int32_t en_tw; /* tag word (16bits) */ + int32_t en_fip; /* fp instruction pointer */ + uint16_t en_fcs; /* fp code segment selector */ + uint16_t en_opcode; /* opcode last executed (11 bits) */ + int32_t en_foo; /* fp operand offset */ + int32_t en_fos; /* fp operand segment selector */ +}; + +/* Contents of each x87 floating point accumulator. */ +struct fpacc87 { + uint8_t fp_bytes[10]; +}; + +/* Floating point context. (i386 fnsave/frstor) */ +struct save87 { + struct env87 sv_env; /* floating point control/status */ + struct fpacc87 sv_ac[8]; /* accumulator contents, 0-7 */ + uint8_t sv_pad0[4]; /* saved status word (now unused) */ + /* + * Bogus padding for emulators. Emulators should use their own + * struct and arrange to store into this struct (ending here) + * before it is inspected for ptracing or for core dumps. Some + * emulators overwrite the whole struct. We have no good way of + * knowing how much padding to leave. Leave just enough for the + * GPL emulator's i387_union (176 bytes total). + */ + uint8_t sv_pad[64]; /* padding; used by emulators */ +}; + +/* Contents of each SSE extended accumulator. */ +struct xmmacc { + uint8_t xmm_bytes[16]; +}; + +/* Contents of the upper 16 bytes of each AVX extended accumulator. */ +struct ymmacc { + uint8_t ymm_bytes[16]; +}; + +/* Rename structs below depending on machine architecture. */ +#ifdef __i386__ +#define __envxmm32 envxmm +#else +#define __envxmm32 envxmm32 +#define __envxmm64 envxmm +#endif + +struct __envxmm32 { + uint16_t en_cw; /* control word (16bits) */ + uint16_t en_sw; /* status word (16bits) */ + uint16_t en_tw; /* tag word (16bits) */ + uint16_t en_opcode; /* opcode last executed (11 bits) */ + uint32_t en_fip; /* fp instruction pointer */ + uint16_t en_fcs; /* fp code segment selector */ + uint16_t en_pad0; /* padding */ + uint32_t en_foo; /* fp operand offset */ + uint16_t en_fos; /* fp operand segment selector */ + uint16_t en_pad1; /* padding */ + uint32_t en_mxcsr; /* SSE control/status register */ + uint32_t en_mxcsr_mask; /* valid bits in mxcsr */ +}; + +struct __envxmm64 { + uint16_t en_cw; /* control word (16bits) */ + uint16_t en_sw; /* status word (16bits) */ + uint8_t en_tw; /* tag word (8bits) */ + uint8_t en_zero; + uint16_t en_opcode; /* opcode last executed (11 bits ) */ + uint64_t en_rip; /* fp instruction pointer */ + uint64_t en_rdp; /* fp operand pointer */ + uint32_t en_mxcsr; /* SSE control/status register */ + uint32_t en_mxcsr_mask; /* valid bits in mxcsr */ +}; + +/* Floating point context. (i386 fxsave/fxrstor) */ +struct savexmm { + struct __envxmm32 sv_env; + struct { + struct fpacc87 fp_acc; + uint8_t fp_pad[6]; /* padding */ + } sv_fp[8]; + struct xmmacc sv_xmm[8]; + uint8_t sv_pad[224]; +} __aligned(16); + +#ifdef __i386__ +union savefpu { + struct save87 sv_87; + struct savexmm sv_xmm; +}; +#else +/* Floating point context. (amd64 fxsave/fxrstor) */ +struct savefpu { + struct __envxmm64 sv_env; + struct { + struct fpacc87 fp_acc; + uint8_t fp_pad[6]; /* padding */ + } sv_fp[8]; + struct xmmacc sv_xmm[16]; + uint8_t sv_pad[96]; +} __aligned(16); +#endif + +struct xstate_hdr { + uint64_t xstate_bv; + uint8_t xstate_rsrv0[16]; + uint8_t xstate_rsrv[40]; +}; + +struct savexmm_xstate { + struct xstate_hdr sx_hd; + struct ymmacc sx_ymm[16]; +}; + +struct savexmm_ymm { + struct __envxmm32 sv_env; + struct { + struct fpacc87 fp_acc; + int8_t fp_pad[6]; /* padding */ + } sv_fp[8]; + struct xmmacc sv_xmm[16]; + uint8_t sv_pad[96]; + struct savexmm_xstate sv_xstate; +} __aligned(64); + +struct savefpu_xstate { + struct xstate_hdr sx_hd; + struct ymmacc sx_ymm[16]; +}; + +struct savefpu_ymm { + struct __envxmm64 sv_env; + struct { + struct fpacc87 fp_acc; + int8_t fp_pad[6]; /* padding */ + } sv_fp[8]; + struct xmmacc sv_xmm[16]; + uint8_t sv_pad[96]; + struct savefpu_xstate sv_xstate; +} __aligned(64); + +#undef __envxmm32 +#undef __envxmm64 + +/* + * The hardware default control word for i387's and later coprocessors is + * 0x37F, giving: + * + * round to nearest + * 64-bit precision + * all exceptions masked. + * + * FreeBSD/i386 uses 53 bit precision for things like fadd/fsub/fsqrt etc + * because of the difference between memory and fpu register stack arguments. + * If its using an intermediate fpu register, it has 80/64 bits to work + * with. If it uses memory, it has 64/53 bits to work with. However, + * gcc is aware of this and goes to a fair bit of trouble to make the + * best use of it. + * + * This is mostly academic for AMD64, because the ABI prefers the use + * SSE2 based math. For FreeBSD/amd64, we go with the default settings. + */ +#define __INITIAL_FPUCW__ 0x037F +#define __INITIAL_FPUCW_I386__ 0x127F +#define __INITIAL_NPXCW__ __INITIAL_FPUCW_I386__ +#define __INITIAL_MXCSR__ 0x1F80 +#define __INITIAL_MXCSR_MASK__ 0xFFBF + +#endif /* !_X86_FPU_H_ */ diff --git a/headers/posix/fenv.h b/headers/posix/fenv.h index 0fb1e20..31fdd0b 100644 --- a/headers/posix/fenv.h +++ b/headers/posix/fenv.h @@ -3,7 +3,7 @@ #if defined(__INTEL__) # include <arch/x86/fenv.h> -#elif defined(_x86_64_) +#elif defined(__x86_64__) # include <arch/x86_64/fenv.h> #elif defined(__ARM__) # include <arch/arm/fenv.h> diff --git a/src/system/libroot/posix/arch/x86_64/Jamfile b/src/system/libroot/posix/arch/x86_64/Jamfile index cbbe851..5891f1b 100644 --- a/src/system/libroot/posix/arch/x86_64/Jamfile +++ b/src/system/libroot/posix/arch/x86_64/Jamfile @@ -8,7 +8,7 @@ local genericSources = ; MergeObject posix_arch_$(TARGET_ARCH).o : - #fenv.c + fenv.c sigsetjmp.S siglongjmp.S diff --git a/src/system/libroot/posix/arch/x86_64/fenv.c b/src/system/libroot/posix/arch/x86_64/fenv.c new file mode 100644 index 0000000..861f621 --- /dev/null +++ b/src/system/libroot/posix/arch/x86_64/fenv.c @@ -0,0 +1,158 @@ +/*- + * Copyright (c) 2004-2005 David Schultz <das@xxxxxxxxxxx> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> +#include <sys/types.h> +#include <posix/fenv.h> +#include <arch/x86_64/fpu.h> + +const fenv_t __fe_dfl_env = { + { 0xffff0000 | __INITIAL_FPUCW__, + 0xffff0000, + 0xffffffff, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff } + }, + __INITIAL_MXCSR__ +}; + +extern inline int feclearexcept(int __excepts); +extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts); + +int +fesetexceptflag(const fexcept_t *flagp, int excepts) +{ + fenv_t env; + + __fnstenv(&env.__x87); + env.__x87.__status &= ~excepts; + env.__x87.__status |= *flagp & excepts; + __fldenv(env.__x87); + + __stmxcsr(&env.__mxcsr); + env.__mxcsr &= ~excepts; + env.__mxcsr |= *flagp & excepts; + __ldmxcsr(env.__mxcsr); + + return (0); +} + +int +feraiseexcept(int excepts) +{ + fexcept_t ex = excepts; + + fesetexceptflag(&ex, excepts); + __fwait(); + return (0); +} + +extern inline int fetestexcept(int __excepts); +extern inline int fegetround(void); +extern inline int fesetround(int __round); + +int +fegetenv(fenv_t *envp) +{ + + __fnstenv(&envp->__x87); + __stmxcsr(&envp->__mxcsr); + /* + * fnstenv masks all exceptions, so we need to restore the + * control word to avoid this side effect. + */ + __fldcw(envp->__x87.__control); + return (0); +} + +int +feholdexcept(fenv_t *envp) +{ + uint32_t mxcsr; + + __stmxcsr(&mxcsr); + __fnstenv(&envp->__x87); + __fnclex(); + envp->__mxcsr = mxcsr; + mxcsr &= ~FE_ALL_EXCEPT; + mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT; + __ldmxcsr(mxcsr); + return (0); +} + +extern inline int fesetenv(const fenv_t *__envp); + +int +feupdateenv(const fenv_t *envp) +{ + uint32_t mxcsr; + uint16_t status; + + __fnstsw(&status); + __stmxcsr(&mxcsr); + fesetenv(envp); + feraiseexcept((mxcsr | status) & FE_ALL_EXCEPT); + return (0); +} + +int +__feenableexcept(int mask) +{ + uint32_t mxcsr, omask; + uint16_t control; + + mask &= FE_ALL_EXCEPT; + __fnstcw(&control); + __stmxcsr(&mxcsr); + omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT; + control &= ~mask; + __fldcw(control); + mxcsr &= ~(mask << _SSE_EMASK_SHIFT); + __ldmxcsr(mxcsr); + return (omask); +} + +int +__fedisableexcept(int mask) +{ + uint32_t mxcsr, omask; + uint16_t control; + + mask &= FE_ALL_EXCEPT; + __fnstcw(&control); + __stmxcsr(&mxcsr); + omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT; + control |= mask; + __fldcw(control); + mxcsr |= mask << _SSE_EMASK_SHIFT; + __ldmxcsr(mxcsr); + return (omask); +} + +__weak_reference(__feenableexcept, feenableexcept); +__weak_reference(__fedisableexcept, fedisableexcept);