From ddcd7a8df8686d161de42b31b817a920ab575117 Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Mon, 22 Nov 2004 22:54:53 +0000 Subject: [PATCH] Implement some functions on systems that don't support them yet. This includes Cygwin/x86. The code is derived from the GNU C Library. --- .../src/kpx_cpu/src/mathlib/ieeefp-i386.cpp | 110 ++++++++++++++++++ .../src/kpx_cpu/src/mathlib/ieeefp-i386.hpp | 52 +++++++++ .../src/kpx_cpu/src/mathlib/ieeefp.cpp | 29 +++++ .../src/kpx_cpu/src/mathlib/ieeefp.hpp | 38 ++++++ 4 files changed, 229 insertions(+) create mode 100755 SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-i386.cpp create mode 100755 SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-i386.hpp create mode 100755 SheepShaver/src/kpx_cpu/src/mathlib/ieeefp.cpp create mode 100755 SheepShaver/src/kpx_cpu/src/mathlib/ieeefp.hpp diff --git a/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-i386.cpp b/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-i386.cpp new file mode 100755 index 00000000..11ff3bfa --- /dev/null +++ b/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-i386.cpp @@ -0,0 +1,110 @@ +/* + * ieeefp-i386.cpp - Access to FPU environment, x86 specific code + * + * Kheperix (C) 2003-2004 Gwenole Beauchesne + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * CPU features + */ + +/* XXX: duplicate from cpu/ppc/ppc-dyngen.cpp! */ +static uint32 cpu_features = 0; + +enum { + HWCAP_I386_CMOV = 1 << 15, + HWCAP_I386_MMX = 1 << 23, + HWCAP_I386_SSE = 1 << 25, + HWCAP_I386_SSE2 = 1 << 26, +}; + +static unsigned int x86_cpuid(void) +{ + int fl1, fl2; + + /* See if we can use cpuid. On AMD64 we always can. */ + __asm__ ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;" + "pushl %0; popfl; pushfl; popl %0; popfl" + : "=&r" (fl1), "=&r" (fl2) + : "i" (0x00200000)); + if (((fl1 ^ fl2) & 0x00200000) == 0) + return (0); + + /* Host supports cpuid. See if cpuid gives capabilities, try + CPUID(0). Preserve %ebx and %ecx; cpuid insn clobbers these, we + don't need their CPUID values here, and %ebx may be the PIC + register. */ + __asm__ ("push %%ecx ; push %%ebx ; cpuid ; pop %%ebx ; pop %%ecx" + : "=a" (fl1) : "0" (0) : "edx", "cc"); + if (fl1 == 0) + return (0); + + /* Invoke CPUID(1), return %edx; caller can examine bits to + determine what's supported. */ + __asm__ ("push %%ecx ; push %%ebx ; cpuid ; pop %%ebx ; pop %%ecx" : "=d" (fl2) : "a" (1) : "cc"); + + return fl2; +} + +static inline int has_cpu_features(int test_cpu_features) +{ + static bool initted = false; + if (!initted) { + cpu_features = x86_cpuid(); + initted = true; + } + return cpu_features & test_cpu_features; +} + + +/* + * Rounding control + */ + +// Get current rounding direction +int fegetround(void) +{ + unsigned short cw; + + __asm__ __volatile__("fnstcw %0" : "=m" (*&cw)); + + return cw & 0xc00; +} + +// Set the rounding direction represented by ROUND +int fesetround(int round) +{ + unsigned short cw; + + if ((round & ~0xc00) != 0) + return 1; + + __asm__ __volatile__("fnstcw %0" : "=m" (*&cw)); + cw &= ~0xc00; + cw |= round; + __asm__ __volatile__("fldcw %0" : : "m" (*&cw)); + + if (has_cpu_features(HWCAP_I386_SSE) != 0) { + uint32 xcw; + __asm__ __volatile__("stmxcsr %0" : "=m" (*&xcw)); + xcw &= ~0x6000; + xcw |= round << 3; + __asm__ __volatile__("ldmxcsr %0" : : "m" (*&xcw)); + } + + return 0; +} diff --git a/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-i386.hpp b/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-i386.hpp new file mode 100755 index 00000000..c453a549 --- /dev/null +++ b/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-i386.hpp @@ -0,0 +1,52 @@ +/* + * ieeefp-i386.hpp - Access to FPU environment, x86 specific code + * + * Kheperix (C) 2003-2004 Gwenole Beauchesne + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef IEEEFP_FENV_I386_H +#define IEEEFP_FENV_I386_H + +// Exceptions +enum { + FE_INVALID = 0x01, +#define FE_INVALID FE_INVALID + FE_DIVBYZERO = 0x04, +#define FE_DIVBYZERO FE_DIVBYZERO + FE_OVERFLOW = 0x08, +#define FE_OVERFLOW FE_OVERFLOW + FE_UNDERFLOW = 0x10, +#define FE_UNDERFLOW FE_UNDERFLOW + FE_INEXACT = 0x20 +#define FE_INEXACT FE_INEXACT +}; + +#define FE_ALL_EXCEPT (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) + +// Rounding modes +enum { + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + FE_DOWNWARD = 0x400, +#define FE_DOWNWARD FE_DOWNWARD + FE_UPWARD = 0x800, +#define FE_UPWARD FE_UPWARD + FE_TOWARDZERO = 0xc00 +#define FE_TOWARDZERO FE_TOWARDZERO +}; + +#endif /* IEEEFP_FENV_I386_H */ diff --git a/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp.cpp b/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp.cpp new file mode 100755 index 00000000..5e1aa6a0 --- /dev/null +++ b/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp.cpp @@ -0,0 +1,29 @@ +/* + * ieeefp.cpp - Access to FPU environment + * + * Kheperix (C) 2003-2004 Gwenole Beauchesne + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "sysdeps.h" + +#ifndef HAVE_FENV_H +#include "mathlib/ieeefp.hpp" +#if defined(__i386__) +#include "mathlib/ieeefp-i386.cpp" +#endif +#endif + diff --git a/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp.hpp b/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp.hpp new file mode 100755 index 00000000..932cc8e6 --- /dev/null +++ b/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp.hpp @@ -0,0 +1,38 @@ +/* + * ieeefp.hpp - Access to FPU environment + * + * Kheperix (C) 2003-2004 Gwenole Beauchesne + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef IEEEFP_FENV_H +#define IEEEFP_FENV_H + +#ifdef HAVE_FENV_H +#include +#else + +// Arch-dependent definitions +#if defined(__i386__) +#include "mathlib/ieeefp-i386.hpp" +#endif + +// Rounding control +extern "C" int fegetround(void); +extern "C" int fesetround(int); + +#endif /* FENV_H */ +#endif /* IEEEFP_FENV_H */