macemu/BasiliskII/src/uae_cpu/fpu/rounding.h

160 lines
5.7 KiB
C

/*
* fpu/rounding.h - system-dependant FPU rounding mode and precision
*
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* ARAnyM 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.
*
* ARAnyM 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 ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef FPU_ROUNDING_H
#define FPU_ROUNDING_H
/* NOTE: this file shall be included from fpu/fpu_*.cpp */
#undef PUBLIC
#define PUBLIC extern
#undef PRIVATE
#define PRIVATE static
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* Defaults to generic rounding mode and precision handling */
#define FPU_USE_GENERIC_ROUNDING_MODE
#define FPU_USE_GENERIC_ROUNDING_PRECISION
/* -------------------------------------------------------------------------- */
/* --- Selection of floating-point rounding mode and precision --- */
/* -------------------------------------------------------------------------- */
/* Optimized i386 fpu core must use native rounding mode */
#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_ROUNDING_MODE
# define FPU_USE_X86_ROUNDING_MODE
#endif
/* Optimized i386 fpu core must use native rounding precision */
#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_ROUNDING_PRECISION
# define FPU_USE_X86_ROUNDING_PRECISION
#endif
#if 0 // gb-- FIXME: that doesn't work
/* IEEE-based fpu core can have native rounding mode on i386 */
#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_ROUNDING_MODE
# define FPU_USE_X86_ROUNDING_MODE
#endif
/* IEEE-based fpu core can have native rounding precision on i386 */
#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_ROUNDING_PRECISION
# define FPU_USE_X86_ROUNDING_PRECISION
#endif
#endif
/* -------------------------------------------------------------------------- */
/* --- Sanity checks --- */
/* -------------------------------------------------------------------------- */
/* X86 rounding mode and precision work together */
#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION)
# define FPU_USE_X86_ROUNDING
# define CW_INITIAL (CW_RESET|CW_X|CW_PC_EXTENDED|CW_RC_NEAR|CW_PM|CW_UM|CW_OM|CW_ZM|CW_DM|CW_IM)
PRIVATE uae_u32 x86_control_word;
#endif
/* Control word -- rounding mode */
#ifdef FPU_USE_X86_ROUNDING_MODE
PUBLIC const uae_u32 x86_control_word_rm_mac2host[];
#endif
/* Control word -- rounding precision */
#ifdef FPU_USE_X86_ROUNDING_PRECISION
PUBLIC const uae_u32 x86_control_word_rp_mac2host[];
#endif
#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION)
/* Set host control word for rounding mode and rounding precision */
PRIVATE inline void set_host_control_word(void)
{
/*
Exception enable byte is ignored, but the same value is returned
that was previously set.
*/
x86_control_word
= (x86_control_word & ~(X86_ROUNDING_MODE|X86_ROUNDING_PRECISION))
| x86_control_word_rm_mac2host[(FPU fpcr.rounding_mode & FPCR_ROUNDING_MODE) >> 4]
| x86_control_word_rp_mac2host[(FPU fpcr.rounding_precision & FPCR_ROUNDING_PRECISION) >> 6]
;
__asm__ __volatile__("fldcw %0" : : "m" (x86_control_word));
}
#endif
/* -------------------------------------------------------------------------- */
/* --- Generic rounding mode and precision --- */
/* -------------------------------------------------------------------------- */
#if defined(FPU_USE_GENERIC_ROUNDING_MODE) && defined(FPU_USE_GENERIC_ROUNDING_PRECISION)
/* Set host control word for rounding mode and rounding precision */
PRIVATE inline void set_host_control_word(void)
{ }
#endif
/* -------------------------------------------------------------------------- */
/* --- Common rounding mode and precision --- */
/* -------------------------------------------------------------------------- */
#if defined(FPU_USE_GENERIC_ROUNDING_MODE) || defined(FPU_USE_X86_ROUNDING_MODE)
/* Return the current rounding mode in m68k format */
static inline uae_u32 FFPU get_rounding_mode(void)
{ return FPU fpcr.rounding_mode; }
/* Convert and set to native rounding mode */
static inline void FFPU set_rounding_mode(uae_u32 new_rounding_mode)
{ FPU fpcr.rounding_mode = new_rounding_mode; }
#endif
#if defined(FPU_USE_GENERIC_ROUNDING_PRECISION) || defined(FPU_USE_X86_ROUNDING_PRECISION)
/* Return the current rounding precision in m68k format */
static inline uae_u32 FFPU get_rounding_precision(void)
{ return FPU fpcr.rounding_precision; }
/* Convert and set to native rounding precision */
static inline void FFPU set_rounding_precision(uae_u32 new_rounding_precision)
{ FPU fpcr.rounding_precision = new_rounding_precision; }
#endif
#endif /* FPU_ROUNDING_H */