* Basilisk II JIT integration, phase 2:

- Add new FPU core architecture
- Clean fpu_x86_asm.h as it is no longer automatically generated
This commit is contained in:
gbeauche 2002-09-13 12:50:40 +00:00
parent d3bda319a8
commit c327eee41b
19 changed files with 8862 additions and 3840 deletions

View File

@ -0,0 +1,249 @@
/*
* fpu/core.h - base fpu context definition
*
* Basilisk II (C) 1997-1999 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* 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 FPU_CORE_H
#define FPU_CORE_H
#include "sysdeps.h"
#include "fpu/types.h"
/* ========================================================================== */
/* ========================= FPU CONTEXT DEFINITION ========================= */
/* ========================================================================== */
/* We don't use all features of the C++ language so that we may still
* easily backport that code to C.
*/
struct fpu_t {
/* ---------------------------------------------------------------------- */
/* --- Floating-Point Data Registers --- */
/* ---------------------------------------------------------------------- */
/* The eight %fp0 .. %fp7 registers */
fpu_register registers[8];
/* Used for lazy evalualation of FPU flags */
fpu_register result;
/* ---------------------------------------------------------------------- */
/* --- Floating-Point Control Register --- */
/* ---------------------------------------------------------------------- */
struct {
/* Exception Enable Byte */
uae_u32 exception_enable;
#define FPCR_EXCEPTION_ENABLE 0x0000ff00
#define FPCR_EXCEPTION_BSUN 0x00008000
#define FPCR_EXCEPTION_SNAN 0x00004000
#define FPCR_EXCEPTION_OPERR 0x00002000
#define FPCR_EXCEPTION_OVFL 0x00001000
#define FPCR_EXCEPTION_UNFL 0x00000800
#define FPCR_EXCEPTION_DZ 0x00000400
#define FPCR_EXCEPTION_INEX2 0x00000200
#define FPCR_EXCEPTION_INEX1 0x00000100
/* Mode Control Byte Mask */
#define FPCR_MODE_CONTROL 0x000000ff
/* Rounding precision */
uae_u32 rounding_precision;
#define FPCR_ROUNDING_PRECISION 0x000000c0
#define FPCR_PRECISION_SINGLE 0x00000040
#define FPCR_PRECISION_DOUBLE 0x00000080
#define FPCR_PRECISION_EXTENDED 0x00000000
/* Rounding mode */
uae_u32 rounding_mode;
#define FPCR_ROUNDING_MODE 0x00000030
#define FPCR_ROUND_NEAR 0x00000000
#define FPCR_ROUND_ZERO 0x00000010
#define FPCR_ROUND_MINF 0x00000020
#define FPCR_ROUND_PINF 0x00000030
} fpcr;
/* ---------------------------------------------------------------------- */
/* --- Floating-Point Status Register --- */
/* ---------------------------------------------------------------------- */
struct {
/* Floating-Point Condition Code Byte */
uae_u32 condition_codes;
#define FPSR_CCB 0xff000000
#define FPSR_CCB_NEGATIVE 0x08000000
#define FPSR_CCB_ZERO 0x04000000
#define FPSR_CCB_INFINITY 0x02000000
#define FPSR_CCB_NAN 0x01000000
/* Quotient Byte */
uae_u32 quotient;
#define FPSR_QUOTIENT 0x00ff0000
#define FPSR_QUOTIENT_SIGN 0x00800000
#define FPSR_QUOTIENT_VALUE 0x007f0000
/* Exception Status Byte */
uae_u32 exception_status;
#define FPSR_EXCEPTION_STATUS FPCR_EXCEPTION_ENABLE
#define FPSR_EXCEPTION_BSUN FPCR_EXCEPTION_BSUN
#define FPSR_EXCEPTION_SNAN FPCR_EXCEPTION_SNAN
#define FPSR_EXCEPTION_OPERR FPCR_EXCEPTION_OPERR
#define FPSR_EXCEPTION_OVFL FPCR_EXCEPTION_OVFL
#define FPSR_EXCEPTION_UNFL FPCR_EXCEPTION_UNFL
#define FPSR_EXCEPTION_DZ FPCR_EXCEPTION_DZ
#define FPSR_EXCEPTION_INEX2 FPCR_EXCEPTION_INEX2
#define FPSR_EXCEPTION_INEX1 FPCR_EXCEPTION_INEX1
/* Accrued Exception Byte */
uae_u32 accrued_exception;
#define FPSR_ACCRUED_EXCEPTION 0x000000ff
#define FPSR_ACCR_IOP 0x00000080
#define FPSR_ACCR_OVFL 0x00000040
#define FPSR_ACCR_UNFL 0x00000020
#define FPSR_ACCR_DZ 0x00000010
#define FPSR_ACCR_INEX 0x00000008
} fpsr;
/* ---------------------------------------------------------------------- */
/* --- Floating-Point Instruction Address Register --- */
/* ---------------------------------------------------------------------- */
uae_u32 instruction_address;
/* ---------------------------------------------------------------------- */
/* --- Initialization / Finalization --- */
/* ---------------------------------------------------------------------- */
/* Flag set if we emulate an integral 68040 FPU */
bool is_integral;
/* ---------------------------------------------------------------------- */
/* --- Extra FPE-dependant defines --- */
/* ---------------------------------------------------------------------- */
#if defined(FPU_X86) \
|| (defined(FPU_UAE) && defined(X86_ASSEMBLY)) \
|| (defined(FPU_IEEE) && defined(X86_ASSEMBLY))
#define CW_RESET 0x0040 // initial CW value after RESET
#define CW_FINIT 0x037F // initial CW value after FINIT
#define SW_RESET 0x0000 // initial SW value after RESET
#define SW_FINIT 0x0000 // initial SW value after FINIT
#define TW_RESET 0x5555 // initial TW value after RESET
#define TW_FINIT 0x0FFF // initial TW value after FINIT
#define CW_X 0x1000 // infinity control
#define CW_RC_ZERO 0x0C00 // rounding control toward zero
#define CW_RC_UP 0x0800 // rounding control toward +
#define CW_RC_DOWN 0x0400 // rounding control toward -
#define CW_RC_NEAR 0x0000 // rounding control toward even
#define CW_PC_EXTENDED 0x0300 // precision control 64bit
#define CW_PC_DOUBLE 0x0200 // precision control 53bit
#define CW_PC_RESERVED 0x0100 // precision control reserved
#define CW_PC_SINGLE 0x0000 // precision control 24bit
#define CW_PM 0x0020 // precision exception mask
#define CW_UM 0x0010 // underflow exception mask
#define CW_OM 0x0008 // overflow exception mask
#define CW_ZM 0x0004 // zero divide exception mask
#define CW_DM 0x0002 // denormalized operand exception mask
#define CW_IM 0x0001 // invalid operation exception mask
#define SW_B 0x8000 // busy flag
#define SW_C3 0x4000 // condition code flag 3
#define SW_TOP_7 0x3800 // top of stack = ST(7)
#define SW_TOP_6 0x3000 // top of stack = ST(6)
#define SW_TOP_5 0x2800 // top of stack = ST(5)
#define SW_TOP_4 0x2000 // top of stack = ST(4)
#define SW_TOP_3 0x1800 // top of stack = ST(3)
#define SW_TOP_2 0x1000 // top of stack = ST(2)
#define SW_TOP_1 0x0800 // top of stack = ST(1)
#define SW_TOP_0 0x0000 // top of stack = ST(0)
#define SW_C2 0x0400 // condition code flag 2
#define SW_C1 0x0200 // condition code flag 1
#define SW_C0 0x0100 // condition code flag 0
#define SW_ES 0x0080 // error summary status flag
#define SW_SF 0x0040 // stack fault flag
#define SW_PE 0x0020 // precision exception flag
#define SW_UE 0x0010 // underflow exception flag
#define SW_OE 0x0008 // overflow exception flag
#define SW_ZE 0x0004 // zero divide exception flag
#define SW_DE 0x0002 // denormalized operand exception flag
#define SW_IE 0x0001 // invalid operation exception flag
#define X86_ROUNDING_MODE 0x0C00
#define X86_ROUNDING_PRECISION 0x0300
#endif /* FPU_X86 */
};
/* We handle only one global fpu */
extern fpu_t fpu;
/* Return the address of a particular register */
inline fpu_register * const fpu_register_address(int i)
{ return &fpu.registers[i]; }
/* Dump functions for m68k_dumpstate */
extern void fpu_dump_registers(void);
extern void fpu_dump_flags(void);
/* Accessors to FPU Control Register */
extern inline uae_u32 get_fpcr(void);
extern inline void set_fpcr(uae_u32 new_fpcr);
/* Accessors to FPU Status Register */
extern inline uae_u32 get_fpsr(void);
extern void set_fpsr(uae_u32 new_fpsr);
/* Accessors to FPU Instruction Address Register */
extern inline uae_u32 get_fpiar();
extern inline void set_fpiar(uae_u32 new_fpiar);
/* Initialization / Finalization */
extern void fpu_init(bool integral_68040);
extern void fpu_exit(void);
extern void fpu_reset(void);
/* Floating-point arithmetic instructions */
void fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) REGPARAM;
/* Floating-point program control operations */
void fpuop_bcc(uae_u32 opcode, uaecptr pc, uae_u32 extra) REGPARAM;
void fpuop_dbcc(uae_u32 opcode, uae_u32 extra) REGPARAM;
void fpuop_scc(uae_u32 opcode, uae_u32 extra) REGPARAM;
/* Floating-point system control operations */
void fpuop_save(uae_u32 opcode) REGPARAM;
void fpuop_restore(uae_u32 opcode) REGPARAM;
void fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) REGPARAM;
#endif /* FPU_CORE_H */

View File

@ -0,0 +1,188 @@
/*
* fpu/exceptions.cpp - system-dependant FPU exceptions management
*
* Basilisk II (C) 1997-1999 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* 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
*/
#undef PRIVATE
#define PRIVATE /**/
#undef PUBLIC
#define PUBLIC /**/
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* -------------------------------------------------------------------------- */
/* --- Native X86 exceptions --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_X86_EXCEPTIONS
void FFPU fpu_init_native_exceptions(void)
{
// Mapping for "sw" -> fpsr exception byte
for (uae_u32 i = 0; i < 0x80; i++) {
exception_host2mac[i] = 0;
if(i & SW_FAKE_BSUN) {
exception_host2mac[i] |= FPSR_EXCEPTION_BSUN;
}
// precision exception
if(i & SW_PE) {
exception_host2mac[i] |= FPSR_EXCEPTION_INEX2;
}
// underflow exception
if(i & SW_UE) {
exception_host2mac[i] |= FPSR_EXCEPTION_UNFL;
}
// overflow exception
if(i & SW_OE) {
exception_host2mac[i] |= FPSR_EXCEPTION_OVFL;
}
// zero divide exception
if(i & SW_ZE) {
exception_host2mac[i] |= FPSR_EXCEPTION_DZ;
}
// denormalized operand exception.
// wrong, but should not get here, normalization is done in elsewhere
if(i & SW_DE) {
exception_host2mac[i] |= FPSR_EXCEPTION_SNAN;
}
// invalid operation exception
if(i & SW_IE) {
exception_host2mac[i] |= FPSR_EXCEPTION_OPERR;
}
}
// Mapping for fpsr exception byte -> "sw"
for (uae_u32 i = 0; i < 0x100; i++) {
uae_u32 fpsr = (i << 8);
exception_mac2host[i] = 0;
// BSUN; make sure that you don't generate FPU stack faults.
if(fpsr & FPSR_EXCEPTION_BSUN) {
exception_mac2host[i] |= SW_FAKE_BSUN;
}
// precision exception
if(fpsr & FPSR_EXCEPTION_INEX2) {
exception_mac2host[i] |= SW_PE;
}
// underflow exception
if(fpsr & FPSR_EXCEPTION_UNFL) {
exception_mac2host[i] |= SW_UE;
}
// overflow exception
if(fpsr & FPSR_EXCEPTION_OVFL) {
exception_mac2host[i] |= SW_OE;
}
// zero divide exception
if(fpsr & FPSR_EXCEPTION_DZ) {
exception_mac2host[i] |= SW_ZE;
}
// denormalized operand exception
if(fpsr & FPSR_EXCEPTION_SNAN) {
exception_mac2host[i] |= SW_DE; //Wrong
}
// invalid operation exception
if(fpsr & FPSR_EXCEPTION_OPERR) {
exception_mac2host[i] |= SW_IE;
}
}
}
#endif
#ifdef FPU_USE_X86_ACCRUED_EXCEPTIONS
void FFPU fpu_init_native_accrued_exceptions(void)
{
/*
68881/68040 accrued exceptions accumulate as follows:
Accrued.IOP |= (Exception.SNAN | Exception.OPERR)
Accrued.OVFL |= (Exception.OVFL)
Accrued.UNFL |= (Exception.UNFL | Exception.INEX2)
Accrued.DZ |= (Exception.DZ)
Accrued.INEX |= (Exception.INEX1 | Exception.INEX2 | Exception.OVFL)
*/
// Mapping for "fpsr.accrued_exception" -> fpsr accrued exception byte
for (uae_u32 i = 0; i < 0x40; i++ ) {
accrued_exception_host2mac[i] = 0;
// precision exception
if(i & SW_PE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_INEX;
}
// underflow exception
if(i & SW_UE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_UNFL;
}
// overflow exception
if(i & SW_OE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_OVFL;
}
// zero divide exception
if(i & SW_ZE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_DZ;
}
// denormalized operand exception
if(i & SW_DE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_IOP; //??????
}
// invalid operation exception
if(i & SW_IE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_IOP;
}
}
// Mapping for fpsr accrued exception byte -> "fpsr.accrued_exception"
for (uae_u32 i = 0; i < 0x20; i++) {
int fpsr = (i << 3);
accrued_exception_mac2host[i] = 0;
// precision exception
if(fpsr & FPSR_ACCR_INEX) {
accrued_exception_mac2host[i] |= SW_PE;
}
// underflow exception
if(fpsr & FPSR_ACCR_UNFL) {
accrued_exception_mac2host[i] |= SW_UE;
}
// overflow exception
if(fpsr & FPSR_ACCR_OVFL) {
accrued_exception_mac2host[i] |= SW_OE;
}
// zero divide exception
if(fpsr & FPSR_ACCR_DZ) {
accrued_exception_mac2host[i] |= SW_ZE;
}
// What about SW_DE; //??????
// invalid operation exception
if(fpsr & FPSR_ACCR_IOP) {
accrued_exception_mac2host[i] |= SW_IE;
}
}
}
#endif

View File

@ -0,0 +1,149 @@
/*
* fpu/exceptions.h - system-dependant FPU exceptions management
*
* Basilisk II (C) 1997-1999 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* 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 FPU_EXCEPTIONS_H
#define FPU_EXCEPTIONS_H
/* NOTE: this file shall be included only 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 exceptions */
#define FPU_USE_GENERIC_EXCEPTIONS
#define FPU_USE_GENERIC_ACCRUED_EXCEPTIONS
/* -------------------------------------------------------------------------- */
/* --- Selection of floating-point exceptions handling mode --- */
/* -------------------------------------------------------------------------- */
/* Optimized i386 fpu core must use native exceptions */
#if defined(FPU_X86) && defined(X86_ASSEMBLY)
# undef FPU_USE_GENERIC_EXCEPTIONS
# define FPU_USE_X86_EXCEPTIONS
#endif
/* Optimized i386 fpu core must use native accrued exceptions */
#if defined(FPU_X86) && defined(X86_ASSEMBLY)
# undef FPU_USE_GENERIC_ACCRUED_EXCEPTIONS
# define FPU_USE_X86_ACCRUED_EXCEPTIONS
#endif
/* -------------------------------------------------------------------------- */
/* --- Native X86 Exceptions --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_X86_EXCEPTIONS
/* Extend the SW_* codes */
#define SW_FAKE_BSUN SW_SF
/* Shorthand */
#define SW_EXCEPTION_MASK (SW_ES|SW_SF|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)
// #define SW_EXCEPTION_MASK (SW_SF|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)
/* Lookup tables */
PRIVATE uae_u32 exception_host2mac[ 0x80 ];
PRIVATE uae_u32 exception_mac2host[ 0x100 ];
/* Initialize native exception management */
PUBLIC void FFPU fpu_init_native_exceptions(void);
/* Return m68k floating-point exception status */
PRIVATE inline uae_u32 FFPU get_exception_status(void)
{ return exception_host2mac[FPU fpsr.exception_status & (SW_FAKE_BSUN|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)]; }
/* Set new exception status. Assumes mask against FPSR_EXCEPTION to be already performed */
PRIVATE inline void FFPU set_exception_status(uae_u32 new_status)
{ FPU fpsr.exception_status = exception_mac2host[new_status >> 8]; }
#endif /* FPU_USE_X86_EXCEPTIONS */
#ifdef FPU_USE_X86_ACCRUED_EXCEPTIONS
/* Lookup tables */
PRIVATE uae_u32 accrued_exception_host2mac[ 0x40 ];
PRIVATE uae_u32 accrued_exception_mac2host[ 0x20 ];
/* Initialize native accrued exception management */
PUBLIC void FFPU fpu_init_native_accrued_exceptions(void);
/* Return m68k accrued exception byte */
PRIVATE inline uae_u32 FFPU get_accrued_exception(void)
{ return accrued_exception_host2mac[FPU fpsr.accrued_exception & (SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)]; }
/* Set new accrued exception byte */
PRIVATE inline void FFPU set_accrued_exception(uae_u32 new_status)
{ FPU fpsr.accrued_exception = accrued_exception_mac2host[(new_status & 0xF8) >> 3]; }
#endif /* FPU_USE_X86_ACCRUED_EXCEPTIONS */
/* -------------------------------------------------------------------------- */
/* --- Default Exceptions Handling --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_GENERIC_EXCEPTIONS
/* Initialize native exception management */
PUBLIC inline void FFPU fpu_init_native_exceptions(void)
{ }
/* Return m68k floating-point exception status */
PRIVATE inline uae_u32 FFPU get_exception_status(void)
{ return FPU fpsr.exception_status; }
/* Set new exception status. Assumes mask against FPSR_EXCEPTION to be already performed */
PRIVATE inline void FFPU set_exception_status(uae_u32 new_status)
{ FPU fpsr.exception_status = new_status; }
#endif /* FPU_USE_GENERIC_EXCEPTIONS */
#ifdef FPU_USE_GENERIC_ACCRUED_EXCEPTIONS
/* Initialize native accrued exception management */
PRIVATE inline void FFPU fpu_init_native_accrued_exceptions(void)
{ }
/* Return m68k accrued exception byte */
PRIVATE inline uae_u32 FFPU get_accrued_exception(void)
{ return FPU fpsr.accrued_exception; }
/* Set new accrued exception byte */
PRIVATE inline void FFPU set_accrued_exception(uae_u32 new_status)
{ FPU fpsr.accrued_exception = new_status; }
#endif /* FPU_USE_GENERIC_ACCRUED_EXCEPTIONS */
#endif /* FPU_EXCEPTIONS_H */

View File

@ -0,0 +1,169 @@
/*
* fpu/flags.cpp - Floating-point flags
*
* Basilisk II (C) 1997-1999 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* 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
*/
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */
#undef PRIVATE
#define PRIVATE /**/
#undef PUBLIC
#define PUBLIC /**/
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* -------------------------------------------------------------------------- */
/* --- Native X86 floating-point flags --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_X86_FLAGS
/* Initialization */
void FFPU fpu_init_native_fflags(void)
{
// Adapted from fpu_x86.cpp
#define SW_Z_I_NAN_MASK (SW_C0|SW_C2|SW_C3)
#define SW_Z (SW_C3)
#define SW_I (SW_C0|SW_C2)
#define SW_NAN (SW_C0)
#define SW_FINITE (SW_C2)
#define SW_EMPTY_REGISTER (SW_C0|SW_C3)
#define SW_DENORMAL (SW_C2|SW_C3)
#define SW_UNSUPPORTED (0)
#define SW_N (SW_C1)
// Sanity checks
#if (SW_Z != NATIVE_FFLAG_ZERO)
#error "Incorrect X86 Z fflag"
#endif
#if (SW_I != NATIVE_FFLAG_INFINITY)
#error "Incorrect X86 I fflag"
#endif
#if (SW_N != NATIVE_FFLAG_NEGATIVE)
#error "Incorrect X86 N fflag"
#endif
#if (SW_NAN != NATIVE_FFLAG_NAN)
#error "Incorrect X86 NAN fflag"
#endif
// Native status word to m68k mappings
for (uae_u32 i = 0; i < 0x48; i++) {
to_m68k_fpcond[i] = 0;
const uae_u32 native_fpcond = i << 8;
switch (native_fpcond & SW_Z_I_NAN_MASK) {
#ifndef FPU_UAE
// gb-- enabling it would lead to incorrect drawing of digits
// in Speedometer Performance Test
case SW_UNSUPPORTED:
#endif
case SW_NAN:
case SW_EMPTY_REGISTER:
to_m68k_fpcond[i] |= FPSR_CCB_NAN;
break;
case SW_FINITE:
case SW_DENORMAL:
break;
case SW_I:
to_m68k_fpcond[i] |= FPSR_CCB_INFINITY;
break;
case SW_Z:
to_m68k_fpcond[i] |= FPSR_CCB_ZERO;
break;
}
if (native_fpcond & SW_N)
to_m68k_fpcond[i] |= FPSR_CCB_NEGATIVE;
}
// m68k to native status word mappings
for (uae_u32 i = 0; i < 0x10; i++) {
const uae_u32 m68k_fpcond = i << 24;
if (m68k_fpcond & FPSR_CCB_NAN)
to_host_fpcond[i] = SW_NAN;
else if (m68k_fpcond & FPSR_CCB_ZERO)
to_host_fpcond[i] = SW_Z;
else if (m68k_fpcond & FPSR_CCB_INFINITY)
to_host_fpcond[i] = SW_I;
else
to_host_fpcond[i] = SW_FINITE;
if (m68k_fpcond & FPSR_CCB_NEGATIVE)
to_host_fpcond[i] |= SW_N;
}
// truth-table for FPU conditions
for (uae_u32 host_fpcond = 0; host_fpcond < 0x08; host_fpcond++) {
// host_fpcond: C3 on bit 2, C1 and C0 are respectively on bits 1 and 0
const uae_u32 real_host_fpcond = ((host_fpcond & 4) << 12) | ((host_fpcond & 3) << 8);
const bool N = ((real_host_fpcond & NATIVE_FFLAG_NEGATIVE) == NATIVE_FFLAG_NEGATIVE);
const bool Z = ((real_host_fpcond & NATIVE_FFLAG_ZERO) == NATIVE_FFLAG_ZERO);
const bool NaN = ((real_host_fpcond & NATIVE_FFLAG_NAN) == NATIVE_FFLAG_NAN);
int value;
for (uae_u32 m68k_fpcond = 0; m68k_fpcond < 0x20; m68k_fpcond++) {
switch (m68k_fpcond) {
case 0x00: value = 0; break; // False
case 0x01: value = Z; break; // Equal
case 0x02: value = !(NaN || Z || N); break; // Ordered Greater Than
case 0x03: value = Z || !(NaN || N); break; // Ordered Greater Than or Equal
case 0x04: value = N && !(NaN || Z); break; // Ordered Less Than
case 0x05: value = Z || (N && !NaN); break; // Ordered Less Than or Equal
case 0x06: value = !(NaN || Z); break; // Ordered Greater or Less Than
case 0x07: value = !NaN; break; // Ordered
case 0x08: value = NaN; break; // Unordered
case 0x09: value = NaN || Z; break; // Unordered or Equal
case 0x0a: value = NaN || !(N || Z); break; // Unordered or Greater Than
case 0x0b: value = NaN || Z || !N; break; // Unordered or Greater or Equal
case 0x0c: value = NaN || (N && !Z); break; // Unordered or Less Than
case 0x0d: value = NaN || Z || N; break; // Unordered or Less or Equal
case 0x0e: value = !Z; break; // Not Equal
case 0x0f: value = 1; break; // True
case 0x10: value = 0; break; // Signaling False
case 0x11: value = Z; break; // Signaling Equal
case 0x12: value = !(NaN || Z || N); break; // Greater Than
case 0x13: value = Z || !(NaN || N); break; // Greater Than or Equal
case 0x14: value = N && !(NaN || Z); break; // Less Than
case 0x15: value = Z || (N && !NaN); break; // Less Than or Equal
case 0x16: value = !(NaN || Z); break; // Greater or Less Than
case 0x17: value = !NaN; break; // Greater, Less or Equal
case 0x18: value = NaN; break; // Not Greater, Less or Equal
case 0x19: value = NaN || Z; break; // Not Greater or Less Than
case 0x1a: value = NaN || !(N || Z); break; // Not Less Than or Equal
case 0x1b: value = NaN || Z || !N; break; // Not Less Than
case 0x1c: value = NaN || (N && !Z); break; // Not Greater Than or Equal
// case 0x1c: value = !Z && (NaN || N); break; // Not Greater Than or Equal
case 0x1d: value = NaN || Z || N; break; // Not Greater Than
case 0x1e: value = !Z; break; // Signaling Not Equal
case 0x1f: value = 1; break; // Signaling True
default: value = -1;
}
fpcond_truth_table[m68k_fpcond][host_fpcond] = value;
}
}
}
#endif

View File

@ -0,0 +1,223 @@
/*
* fpu/flags.h - Floating-point flags
*
* Basilisk II (C) 1997-1999 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* 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 FPU_FLAGS_H
#define FPU_FLAGS_H
/* NOTE: this file shall be included only 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 flags */
#define FPU_USE_GENERIC_FLAGS
/* -------------------------------------------------------------------------- */
/* --- Selection of floating-point flags handling mode --- */
/* -------------------------------------------------------------------------- */
/* Optimized i386 fpu core must use native flags */
#if defined(FPU_X86) && defined(X86_ASSEMBLY)
# undef FPU_USE_GENERIC_FLAGS
# define FPU_USE_X86_FLAGS
#endif
/* Old UAE FPU core can use native flags */
#if defined(FPU_UAE) && defined(X86_ASSEMBLY)
# undef FPU_USE_GENERIC_FLAGS
# define FPU_USE_X86_FLAGS
#endif
/* IEEE-based implementation must use lazy flag evaluation */
#if defined(FPU_IEEE)
# undef FPU_USE_GENERIC_FLAGS
# define FPU_USE_LAZY_FLAGS
#endif
/* JIT Compilation for FPU only works with lazy evaluation of FPU flags */
#if defined(FPU_IEEE) && defined(X86_ASSEMBLY) && defined(USE_JIT_FPU)
# undef FPU_USE_GENERIC_FLAGS
# define FPU_USE_LAZY_FLAGS
#endif
#ifdef FPU_IMPLEMENTATION
/* -------------------------------------------------------------------------- */
/* --- Native X86 Floating-Point Flags --- */
/* -------------------------------------------------------------------------- */
/* FPU_X86 has its own set of lookup functions */
#ifdef FPU_USE_X86_FLAGS
#define FPU_USE_NATIVE_FLAGS
#define NATIVE_FFLAG_NEGATIVE 0x0200
#define NATIVE_FFLAG_ZERO 0x4000
#define NATIVE_FFLAG_INFINITY 0x0500
#define NATIVE_FFLAG_NAN 0x0100
/* Translation tables between native and m68k floating-point flags */
PRIVATE uae_u32 to_m68k_fpcond[0x48];
PRIVATE uae_u32 to_host_fpcond[0x10];
/* Truth table for floating-point condition codes */
PRIVATE uae_u32 fpcond_truth_table[32][8]; // 32 m68k conditions x 8 host condition codes
/* Initialization */
PUBLIC void FFPU fpu_init_native_fflags(void);
#ifdef FPU_UAE
/* Native to m68k floating-point condition codes */
PRIVATE inline uae_u32 FFPU get_fpccr(void)
{ return to_m68k_fpcond[(FPU fpsr.condition_codes >> 8) & 0x47]; }
/* M68k to native floating-point condition codes */
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
/* Precondition: new_fpcond is only valid for floating-point condition codes */
{ FPU fpsr.condition_codes = to_host_fpcond[new_fpcond >> 24]; }
/* Make FPSR according to the value passed in argument */
PRIVATE inline void FFPU make_fpsr(fpu_register const & r)
{ uae_u16 sw; __asm__ __volatile__ ("fxam\n\tfnstsw %0" : "=r" (sw) : "f" (r)); FPU fpsr.condition_codes = sw; }
/* Return the corresponding ID of the current floating-point condition codes */
/* NOTE: only valid for evaluation of a condition */
PRIVATE inline int FFPU host_fpcond_id(void)
{ return ((FPU fpsr.condition_codes >> 12) & 4) | ((FPU fpsr.condition_codes >> 8) & 3); }
/* Return true if the floating-point condition is satisfied */
PRIVATE inline bool FFPU fpcctrue(int condition)
{ return fpcond_truth_table[condition][host_fpcond_id()]; }
#endif /* FPU_UAE */
/* Return the address of the floating-point condition codes truth table */
PUBLIC inline uae_u8 * const FFPU address_of_fpcond_truth_table(void)
{ return ((uae_u8*)&fpcond_truth_table[0][0]); }
#endif /* FPU_X86_USE_NATIVE_FLAGS */
/* -------------------------------------------------------------------------- */
/* --- Use Original M68K FPU Mappings --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_GENERIC_FLAGS
#undef FPU_USE_NATIVE_FLAGS
#define NATIVE_FFLAG_NEGATIVE 0x08000000
#define NATIVE_FFLAG_ZERO 0x04000000
#define NATIVE_FFLAG_INFINITY 0x02000000
#define NATIVE_FFLAG_NAN 0x01000000
/* Initialization - NONE */
PRIVATE inline void FFPU fpu_init_native_fflags(void)
{ }
/* Native to m68k floating-point condition codes - SELF */
PRIVATE inline uae_u32 FFPU get_fpccr(void)
{ return FPU fpsr.condition_codes; }
/* M68k to native floating-point condition codes - SELF */
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
{ FPU fpsr.condition_codes = new_fpcond; }
#endif /* FPU_USE_GENERIC_FLAGS */
/* -------------------------------------------------------------------------- */
/* --- Use Lazy Flags Evaluation --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_LAZY_FLAGS
#undef FPU_USE_NATIVE_FLAGS
#define NATIVE_FFLAG_NEGATIVE 0x08000000
#define NATIVE_FFLAG_ZERO 0x04000000
#define NATIVE_FFLAG_INFINITY 0x02000000
#define NATIVE_FFLAG_NAN 0x01000000
/* Initialization - NONE */
PRIVATE inline void FFPU fpu_init_native_fflags(void)
{ }
/* Native to m68k floating-point condition codes - SELF */
PRIVATE inline uae_u32 FFPU get_fpccr(void)
{
uae_u32 fpccr = 0;
if (isnan(FPU result))
fpccr |= FPSR_CCB_NAN;
else if (FPU result == 0.0)
fpccr |= FPSR_CCB_ZERO;
else if (FPU result < 0.0)
fpccr |= FPSR_CCB_NEGATIVE;
if (isinf(FPU result))
fpccr |= FPSR_CCB_INFINITY;
return fpccr;
}
/* M68k to native floating-point condition codes - SELF */
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
{
if (new_fpcond & FPSR_CCB_NAN)
make_nan(FPU result);
else if (new_fpcond & FPSR_CCB_ZERO)
FPU result = 0.0;
else if (new_fpcond & FPSR_CCB_NEGATIVE)
FPU result = -1.0;
else
FPU result = +1.0;
/* gb-- where is Infinity ? */
}
/* Make FPSR according to the value passed in argument */
PRIVATE inline void FFPU make_fpsr(fpu_register const & r)
{ FPU result = r; }
#endif /* FPU_USE_LAZY_FLAGS */
#endif
/* -------------------------------------------------------------------------- */
/* --- Common methods --- */
/* -------------------------------------------------------------------------- */
/* Return the address of the floating-point condition codes register */
PUBLIC inline uae_u32 * const FFPU address_of_fpccr(void)
{ return ((uae_u32 *)& FPU fpsr.condition_codes); }
#endif /* FPU_FLAGS_H */

View File

@ -0,0 +1,49 @@
/*
* fpu/fpu.h - public header
*
* Basilisk II (C) 1997-1999 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* 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 FPU_PUBLIC_HEADER_H
#define FPU_PUBLIC_HEADER_H
#ifndef FPU_DEBUG
#define FPU_DEBUG 0
#endif
#if FPU_DEBUG
#define fpu_debug(args) printf args;
#define FPU_DUMP_REGISTERS 0
#define FPU_DUMP_FIRST_BYTES 0
#else
#define fpu_debug(args) ;
#undef FPU_DUMP_REGISTERS
#undef FPU_DUMP_FIRST_BYTES
#endif
#include "sysdeps.h"
#include "fpu/types.h"
#include "fpu/core.h"
#endif /* FPU_PUBLIC_HEADER_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,149 @@
/*
* fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core
*
* Basilisk II (C) 1997-1999 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* 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 FPU_IEEE_H
#define FPU_IEEE_H
/* NOTE: this file shall be included from fpu/fpu_uae.cpp */
#undef PUBLIC
#define PUBLIC extern
#undef PRIVATE
#define PRIVATE static
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
// Lauri-- full words to avoid partial register stalls.
struct double_flags {
uae_u32 in_range;
uae_u32 zero;
uae_u32 infinity;
uae_u32 nan;
uae_u32 negative;
};
PRIVATE double_flags fl_source;
PRIVATE double_flags fl_dest;
PRIVATE inline void FFPU get_dest_flags(fpu_register const & r);
PRIVATE inline void FFPU get_source_flags(fpu_register const & r);
PRIVATE inline void FFPU make_nan(fpu_register & r);
PRIVATE inline void FFPU make_zero_positive(fpu_register & r);
PRIVATE inline void FFPU make_zero_negative(fpu_register & r);
PRIVATE inline void FFPU make_inf_positive(fpu_register & r);
PRIVATE inline void FFPU make_inf_negative(fpu_register & r);
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add);
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r);
// May be optimized for particular processors
#ifndef FPU_USE_NATIVE_FLAGS
PRIVATE inline void FFPU make_fpsr(fpu_register const & r);
#endif
// Normalize to range 1..2
PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r);
// The sign of the quotient is the exclusive-OR of the sign bits
// of the source and destination operands.
PRIVATE inline uae_u32 FFPU get_quotient_sign(
fpu_register const & ra, fpu_register const & rb
);
// Quotient Byte is loaded with the sign and least significant
// seven bits of the quotient.
PRIVATE inline void FFPU make_quotient(
fpu_register const & quotient, uae_u32 sign
);
// to_single
PRIVATE inline fpu_register FFPU make_single(
uae_u32 value
);
// from_single
PRIVATE inline uae_u32 FFPU extract_single(
fpu_register const & src
);
// to_exten
PRIVATE inline fpu_register FFPU make_extended(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3
);
/*
Would be so much easier with full size floats :(
... this is so vague.
*/
// to_exten_no_normalize
PRIVATE inline void FFPU make_extended_no_normalize(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result
);
// from_exten
PRIVATE inline void FFPU extract_extended(fpu_register const & src,
uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
);
// to_double
PRIVATE inline fpu_register FFPU make_double(
uae_u32 wrd1, uae_u32 wrd2
);
// from_double
PRIVATE inline void FFPU extract_double(fpu_register const & src,
uae_u32 * wrd1, uae_u32 * wrd2
);
PRIVATE inline fpu_register FFPU make_packed(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3
);
PRIVATE inline void FFPU extract_packed(
fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
);
PRIVATE inline int FFPU get_fp_value(
uae_u32 opcode, uae_u16 extra, fpu_register & src
);
PRIVATE inline int FFPU put_fp_value(
uae_u32 opcode, uae_u16 extra, fpu_register const & value
);
PRIVATE inline int FFPU get_fp_ad(
uae_u32 opcode, uae_u32 * ad
);
PRIVATE inline int FFPU fpp_cond(
int condition
);
#endif /* FPU_IEEE_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,212 @@
/*
* fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core
*
* Basilisk II (C) 1997-1999 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* 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 FPU_UAE_H
#define FPU_UAE_H
// Only define if you have IEEE 64 bit doubles.
#define FPU_HAVE_IEEE_DOUBLE 1
/* NOTE: this file shall be included from fpu/fpu_uae.cpp */
#undef PUBLIC
#define PUBLIC extern
#undef PRIVATE
#define PRIVATE static
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
enum {
#ifdef WORDS_BIGENDIAN
FHI = 0,
FLO = 1
#else
FHI = 1,
FLO = 0
#endif
};
// Floating-point rounding support
PRIVATE inline fpu_register round_to_zero(fpu_register const & x);
PRIVATE inline fpu_register round_to_nearest(fpu_register const & x);
#if FPU_HAVE_IEEE_DOUBLE
// Lauri-- full words to avoid partial register stalls.
struct double_flags {
uae_u32 in_range;
uae_u32 zero;
uae_u32 infinity;
uae_u32 nan;
uae_u32 negative;
};
PRIVATE double_flags fl_source;
PRIVATE double_flags fl_dest;
PRIVATE inline void FFPU get_dest_flags(fpu_register const & r);
PRIVATE inline void FFPU get_source_flags(fpu_register const & r);
PRIVATE inline bool FFPU do_isnan(fpu_register const & r);
PRIVATE inline bool FFPU do_isinf(fpu_register const & r);
PRIVATE inline bool FFPU do_isneg(fpu_register const & r);
PRIVATE inline bool FFPU do_iszero(fpu_register const & r);
PRIVATE inline void FFPU make_nan(fpu_register & r);
PRIVATE inline void FFPU make_zero_positive(fpu_register & r);
PRIVATE inline void FFPU make_zero_negative(fpu_register & r);
PRIVATE inline void FFPU make_inf_positive(fpu_register & r);
PRIVATE inline void FFPU make_inf_negative(fpu_register & r);
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add);
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r);
// May be optimized for particular processors
#ifndef FPU_USE_NATIVE_FLAGS
PRIVATE inline void FFPU make_fpsr(fpu_register const & r);
#endif
// Normalize to range 1..2
PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r);
// The sign of the quotient is the exclusive-OR of the sign bits
// of the source and destination operands.
PRIVATE inline uae_u32 FFPU get_quotient_sign(
fpu_register const & ra, fpu_register const & rb
);
// Quotient Byte is loaded with the sign and least significant
// seven bits of the quotient.
PRIVATE inline void FFPU make_quotient(
fpu_register const & quotient, uae_u32 sign
);
// to_single
PRIVATE inline fpu_register FFPU make_single(
uae_u32 value
);
// from_single
PRIVATE inline uae_u32 FFPU extract_single(
fpu_register const & src
);
// to_exten
PRIVATE inline fpu_register FFPU make_extended(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3
);
/*
Would be so much easier with full size floats :(
... this is so vague.
*/
// to_exten_no_normalize
PRIVATE inline void FFPU make_extended_no_normalize(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result
);
// from_exten
PRIVATE inline void FFPU extract_extended(fpu_register const & src,
uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
);
// to_double
PRIVATE inline fpu_register FFPU make_double(
uae_u32 wrd1, uae_u32 wrd2
);
// from_double
PRIVATE inline void FFPU extract_double(fpu_register const & src,
uae_u32 * wrd1, uae_u32 * wrd2
);
#else /* !FPU_HAVE_IEEE_DOUBLE */
// FIXME: may be optimized for particular processors
#ifndef FPU_USE_NATIVE_FLAGS
PRIVATE inline void FFPU make_fpsr(fpu_register const & r);
#endif
// to_single
PRIVATE inline fpu_register make_single(
uae_u32 value
);
// from_single
PRIVATE inline uae_u32 FFPU extract_single(
fpu_register const & src
);
// to exten
PRIVATE inline fpu_register FFPU make_extended(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3
);
// from_exten
PRIVATE inline void FFPU extract_extended(
fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
);
// to_double
PRIVATE inline fpu_register FFPU make_double(
uae_u32 wrd1, uae_u32 wrd2
);
// from_double
PRIVATE inline void FFPU extract_double(
fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2
);
#endif /* FPU_HAVE_IEEE_DOUBLE */
PRIVATE inline fpu_register FFPU make_packed(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3
);
PRIVATE inline void FFPU extract_packed(
fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
);
PRIVATE inline int FFPU get_fp_value(
uae_u32 opcode, uae_u16 extra, fpu_register & src
);
PRIVATE inline int FFPU put_fp_value(
uae_u32 opcode, uae_u16 extra, fpu_register const & value
);
PRIVATE inline int FFPU get_fp_ad(
uae_u32 opcode, uae_u32 * ad
);
PRIVATE inline int FFPU fpp_cond(
int condition
);
#endif /* FPU_UAE_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,15 @@
/*
* fpu_x86.h - 68881/68040 fpu code for x86/Windows and Linux/x86.
* fpu/fpu_x86.h - Extra Definitions for the X86 assembly FPU core
*
* Basilisk II (C) 1997-2001 Christian Bauer
*
* MC68881 emulation
*
* Based on UAE FPU, original copyright 1996 Herman ten Brugge,
* rewritten by Lauri Pesonen 1999-2000,
* accomodated to GCC's Extended Asm syntax by Gwenole Beauchesne 2000.
* Basilisk II (C) 1997-1999 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* 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
@ -24,111 +25,337 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* gb-- defined in newcpu.h
// is_integral: true == 68040, false == 68881
void fpu_set_integral_fpu( bool is_integral );
#ifndef FPU_X86_H
#define FPU_X86_H
// MUST be called before the cpu starts up.
void fpu_init( void );
/* NOTE: this file shall be included from fpu/fpu_x86.cpp */
#undef PUBLIC
#define PUBLIC extern
// Finalize.
void fpu_exit( void );
#undef PRIVATE
#define PRIVATE static
// Soft reset.
void fpu_reset( void );
*/
#undef FFPU
#define FFPU /**/
// The same as original. "ftrapcc_opp" is bound to change soon.
/* gb-- defined in newcpu.h
void REGPARAM2 fpp_opp (uae_u32, uae_u16);
void REGPARAM2 fdbcc_opp (uae_u32, uae_u16);
void REGPARAM2 fscc_opp (uae_u32, uae_u16);
void REGPARAM2 ftrapcc_opp (uae_u32,uaecptr);
void REGPARAM2 fbcc_opp (uae_u32, uaecptr, uae_u32);
void REGPARAM2 fsave_opp (uae_u32);
void REGPARAM2 frestore_opp (uae_u32);
*/
#undef FPU
#define FPU fpu.
/* ---------------------------- Motorola ---------------------------- */
// Status word
PRIVATE uae_u32 x86_status_word;
PRIVATE uae_u32 x86_status_word_accrued;
// Exception byte
#define BSUN 0x00008000
#define SNAN 0x00004000
#define OPERR 0x00002000
#define OVFL 0x00001000
#define UNFL 0x00000800
#define DZ 0x00000400
#define INEX2 0x00000200
#define INEX1 0x00000100
// FPU jump table
typedef void REGPARAM2 ( *fpuop_func )( uae_u32, uae_u32 );
PRIVATE fpuop_func fpufunctbl[65536];
// Accrued exception byte
#define ACCR_IOP 0x80
#define ACCR_OVFL 0x40
#define ACCR_UNFL 0x20
#define ACCR_DZ 0x10
#define ACCR_INEX 0x08
// FPU consistency
PRIVATE uae_u32 checked_sw_atstart;
// fpcr rounding modes
#define ROUND_CONTROL_MASK 0x30
#define ROUND_TO_NEAREST 0
#define ROUND_TO_ZERO 0x10
#define ROUND_TO_NEGATIVE_INFINITY 0x20
#define ROUND_TO_POSITIVE_INFINITY 0x30
// FMOVECR constants supported byt x86 FPU
PRIVATE fpu_register const_pi;
PRIVATE fpu_register const_lg2;
PRIVATE fpu_register const_l2e;
PRIVATE fpu_register const_z;
PRIVATE fpu_register const_ln2;
PRIVATE fpu_register const_1;
// fpcr precision control
#define PRECISION_CONTROL_MASK 0xC0
#define PRECISION_CONTROL_EXTENDED 0
#define PRECISION_CONTROL_DOUBLE 0x80
#define PRECISION_CONTROL_SINGLE 0x40
#define PRECISION_CONTROL_UNDEFINED 0xC0
// FMOVECR constants not not suported by x86 FPU
PRIVATE fpu_register const_e;
PRIVATE fpu_register const_log_10_e;
PRIVATE fpu_register const_ln_10;
PRIVATE fpu_register const_1e1;
PRIVATE fpu_register const_1e2;
PRIVATE fpu_register const_1e4;
PRIVATE fpu_register const_1e8;
PRIVATE fpu_register const_1e16;
PRIVATE fpu_register const_1e32;
PRIVATE fpu_register const_1e64;
PRIVATE fpu_register const_1e128;
PRIVATE fpu_register const_1e256;
PRIVATE fpu_register const_1e512;
PRIVATE fpu_register const_1e1024;
PRIVATE fpu_register const_1e2048;
PRIVATE fpu_register const_1e4096;
// Saved host FPU state
PRIVATE uae_u8 m_fpu_state_original[108]; // 90/94/108
/* ---------------------------- Intel ---------------------------- */
/* -------------------------------------------------------------------------- */
/* --- Methods --- */
/* -------------------------------------------------------------------------- */
#define CW_RESET 0x0040 // initial CW value after RESET
#define CW_FINIT 0x037F // initial CW value after FINIT
#define SW_RESET 0x0000 // initial SW value after RESET
#define SW_FINIT 0x0000 // initial SW value after FINIT
#define TW_RESET 0x5555 // initial TW value after RESET
#define TW_FINIT 0x0FFF // initial TW value after FINIT
// Debug support functions
PRIVATE void FFPU dump_first_bytes_buf(char *b, uae_u8* buf, uae_s32 actual);
PRIVATE char * FFPU etos(fpu_register const & e) REGPARAM;
#define CW_X 0x1000 // infinity control
#define CW_RC_ZERO 0x0C00 // rounding control toward zero
#define CW_RC_UP 0x0800 // rounding control toward +
#define CW_RC_DOWN 0x0400 // rounding control toward -
#define CW_RC_NEAR 0x0000 // rounding control toward even
#define CW_PC_EXTENDED 0x0300 // precision control 64bit
#define CW_PC_DOUBLE 0x0200 // precision control 53bit
#define CW_PC_RESERVED 0x0100 // precision control reserved
#define CW_PC_SINGLE 0x0000 // precision control 24bit
#define CW_PM 0x0020 // precision exception mask
#define CW_UM 0x0010 // underflow exception mask
#define CW_OM 0x0008 // overflow exception mask
#define CW_ZM 0x0004 // zero divide exception mask
#define CW_DM 0x0002 // denormalized operand exception mask
#define CW_IM 0x0001 // invalid operation exception mask
// FPU consistency
PRIVATE void FFPU FPU_CONSISTENCY_CHECK_START(void);
PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *name);
#define SW_B 0x8000 // busy flag
#define SW_C3 0x4000 // condition code flag 3
#define SW_TOP_7 0x3800 // top of stack = ST(7)
#define SW_TOP_6 0x3000 // top of stack = ST(6)
#define SW_TOP_5 0x2800 // top of stack = ST(5)
#define SW_TOP_4 0x2000 // top of stack = ST(4)
#define SW_TOP_3 0x1800 // top of stack = ST(3)
#define SW_TOP_2 0x1000 // top of stack = ST(2)
#define SW_TOP_1 0x0800 // top of stack = ST(1)
#define SW_TOP_0 0x0000 // top of stack = ST(0)
#define SW_C2 0x0400 // condition code flag 2
#define SW_C1 0x0200 // condition code flag 1
#define SW_C0 0x0100 // condition code flag 0
#define SW_ES 0x0080 // error summary status flag
#define SW_SF 0x0040 // stack fault flag
#define SW_PE 0x0020 // precision exception flag
#define SW_UE 0x0010 // underflow exception flag
#define SW_OE 0x0008 // overflow exception flag
#define SW_ZE 0x0004 // zero divide exception flag
#define SW_DE 0x0002 // denormalized operand exception flag
#define SW_IE 0x0001 // invalid operation exception flag
// Get special floating-point value class
PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f);
PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f);
PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f);
PRIVATE __inline__ uae_u32 FFPU IS_NEGATIVE (fpu_register const & f);
#define X86_ROUND_CONTROL_MASK 0x0C00
#define X86_PRECISION_CONTROL_MASK 0x0300
// Make a special floating-point value
PRIVATE __inline__ void FFPU MAKE_NAN (fpu_register & f);
PRIVATE __inline__ void FFPU MAKE_INF_POSITIVE (fpu_register & f);
PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (fpu_register & f);
PRIVATE __inline__ void FFPU MAKE_ZERO_POSITIVE (fpu_register & f);
PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f);
// Conversion from extended floating-point values
PRIVATE uae_s32 FFPU extended_to_signed_32 ( fpu_register const & f ) REGPARAM;
PRIVATE uae_s16 FFPU extended_to_signed_16 ( fpu_register const & f ) REGPARAM;
PRIVATE uae_s8 FFPU extended_to_signed_8 ( fpu_register const & f ) REGPARAM;
PRIVATE fpu_double FFPU extended_to_double( fpu_register const & f ) REGPARAM;
PRIVATE uae_u32 FFPU from_single ( fpu_register const & f ) REGPARAM;
PRIVATE void FFPU from_exten ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3 ) REGPARAM;
PRIVATE void FFPU from_double ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2 ) REGPARAM;
PRIVATE void FFPU from_pack (fpu_double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) REGPARAM;
// Conversion to extended floating-point values
PRIVATE void FFPU signed_to_extended ( uae_s32 x, fpu_register & f ) REGPARAM;
PRIVATE void FFPU double_to_extended ( double x, fpu_register & f ) REGPARAM;
PRIVATE void FFPU to_single ( uae_u32 src, fpu_register & f ) REGPARAM;
PRIVATE void FFPU to_exten_no_normalize ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f ) REGPARAM;
PRIVATE void FFPU to_exten ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f ) REGPARAM;
PRIVATE void FFPU to_double ( uae_u32 wrd1, uae_u32 wrd2, fpu_register & f ) REGPARAM;
PRIVATE fpu_double FFPU to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) REGPARAM;
// Atomic floating-point arithmetic operations
PRIVATE void FFPU do_fmove ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fmove_no_status ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fint ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fintrz ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsqrt ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_ftst ( fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsinh ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_flognp1 ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fetoxm1 ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_ftanh ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fatan ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fasin ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fatanh ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fetox ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_ftwotox ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_ftentox ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_flogn ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_flog10 ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_flog2 ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_facos ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fcosh ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsin ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_ftan ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fabs ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fcos ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fgetexp ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fgetman ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fdiv ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fmod ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_frem ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fmod_dont_set_cw ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_frem_dont_set_cw ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fadd ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsgldiv ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fscale ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsglmul ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsub ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsincos ( fpu_register & dest_sin, fpu_register & dest_cos, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fcmp ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fldpi ( fpu_register & dest ) REGPARAM;
PRIVATE void FFPU do_fldlg2 ( fpu_register & dest ) REGPARAM;
PRIVATE void FFPU do_fldl2e ( fpu_register & dest ) REGPARAM;
PRIVATE void FFPU do_fldz ( fpu_register & dest ) REGPARAM;
PRIVATE void FFPU do_fldln2 ( fpu_register & dest ) REGPARAM;
PRIVATE void FFPU do_fld1 ( fpu_register & dest ) REGPARAM;
// Instructions handlers
PRIVATE void REGPARAM2 FFPU fpuop_illg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmove_2_ea( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_none( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_none( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fldpi( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fldlg2( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_e( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fldl2e( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_log_10_e( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fldz( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fldln2( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_ln_10( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fld1( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e8( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e16( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e32( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e64( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e128( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e256( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e512( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1024( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2048( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4096( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fmove( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fint( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsinh( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fintrz( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsqrt( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_flognp1( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fetoxm1( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_ftanh( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fatan( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fasin( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fatanh( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsin( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_ftan( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fetox( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_ftwotox( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_ftentox( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_flogn( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_flog10( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_flog2( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fabs( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fcosh( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fneg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_facos( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fcos( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fgetexp( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fgetman( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fdiv( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fmod( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_frem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fadd( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fmul( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsgldiv( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fscale( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsglmul( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsub( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsincos( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fcmp( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_ftst( uae_u32 opcode, uae_u32 extra );
// Get & Put floating-point values
PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src) REGPARAM;
PRIVATE int FFPU put_fp_value (fpu_register const & value, uae_u32 opcode, uae_u32 extra) REGPARAM;
PRIVATE int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) REGPARAM;
// Floating-point condition-based instruction handlers
PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition) REGPARAM;
// Misc functions
PRIVATE void __inline__ FFPU set_host_fpu_control_word ();
PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN ();
PRIVATE void __inline__ FFPU build_ex_status ();
PRIVATE void FFPU do_null_frestore ();
PRIVATE void FFPU build_fpp_opp_lookup_table ();
PRIVATE void FFPU set_constant ( fpu_register & f, char *name, double value, uae_s32 mult );
#endif /* FPU_X86_H */

View File

@ -1,115 +1,72 @@
#define DEFINE_X86_ASM_MACRO(name, value) \
#define DEFINE_X86_MACRO(name, value) \
asm(".local " #name "\n\t" #name " = " #value)
DEFINE_X86_ASM_MACRO(BSUN, 0x00008000);
DEFINE_X86_ASM_MACRO(SNAN, 0x00004000);
DEFINE_X86_ASM_MACRO(OPERR, 0x00002000);
DEFINE_X86_ASM_MACRO(OVFL, 0x00001000);
DEFINE_X86_ASM_MACRO(UNFL, 0x00000800);
DEFINE_X86_ASM_MACRO(DZ, 0x00000400);
DEFINE_X86_ASM_MACRO(INEX2, 0x00000200);
DEFINE_X86_ASM_MACRO(INEX1, 0x00000100);
DEFINE_X86_ASM_MACRO(ACCR_IOP, 0x80);
DEFINE_X86_ASM_MACRO(ACCR_OVFL, 0x40);
DEFINE_X86_ASM_MACRO(ACCR_UNFL, 0x20);
DEFINE_X86_ASM_MACRO(ACCR_DZ, 0x10);
DEFINE_X86_ASM_MACRO(ACCR_INEX, 0x08);
DEFINE_X86_ASM_MACRO(ROUND_CONTROL_MASK, 0x30);
DEFINE_X86_ASM_MACRO(ROUND_TO_NEAREST, 0);
DEFINE_X86_ASM_MACRO(ROUND_TO_ZERO, 0x10);
DEFINE_X86_ASM_MACRO(ROUND_TO_NEGATIVE_INFINITY, 0x20);
DEFINE_X86_ASM_MACRO(ROUND_TO_POSITIVE_INFINITY, 0x30);
DEFINE_X86_ASM_MACRO(PRECISION_CONTROL_MASK, 0xC0);
DEFINE_X86_ASM_MACRO(PRECISION_CONTROL_EXTENDED, 0);
DEFINE_X86_ASM_MACRO(PRECISION_CONTROL_DOUBLE, 0x80);
DEFINE_X86_ASM_MACRO(PRECISION_CONTROL_SINGLE, 0x40);
DEFINE_X86_ASM_MACRO(PRECISION_CONTROL_UNDEFINED, 0xC0);
DEFINE_X86_ASM_MACRO(CW_RESET, 0x0040);
DEFINE_X86_ASM_MACRO(CW_FINIT, 0x037F);
DEFINE_X86_ASM_MACRO(SW_RESET, 0x0000);
DEFINE_X86_ASM_MACRO(SW_FINIT, 0x0000);
DEFINE_X86_ASM_MACRO(TW_RESET, 0x5555);
DEFINE_X86_ASM_MACRO(TW_FINIT, 0x0FFF);
DEFINE_X86_ASM_MACRO(CW_X, 0x1000);
DEFINE_X86_ASM_MACRO(CW_RC_ZERO, 0x0C00);
DEFINE_X86_ASM_MACRO(CW_RC_UP, 0x0800);
DEFINE_X86_ASM_MACRO(CW_RC_DOWN, 0x0400);
DEFINE_X86_ASM_MACRO(CW_RC_NEAR, 0x0000);
DEFINE_X86_ASM_MACRO(CW_PC_EXTENDED, 0x0300);
DEFINE_X86_ASM_MACRO(CW_PC_DOUBLE, 0x0200);
DEFINE_X86_ASM_MACRO(CW_PC_RESERVED, 0x0100);
DEFINE_X86_ASM_MACRO(CW_PC_SINGLE, 0x0000);
DEFINE_X86_ASM_MACRO(CW_PM, 0x0020);
DEFINE_X86_ASM_MACRO(CW_UM, 0x0010);
DEFINE_X86_ASM_MACRO(CW_OM, 0x0008);
DEFINE_X86_ASM_MACRO(CW_ZM, 0x0004);
DEFINE_X86_ASM_MACRO(CW_DM, 0x0002);
DEFINE_X86_ASM_MACRO(CW_IM, 0x0001);
DEFINE_X86_ASM_MACRO(SW_B, 0x8000);
DEFINE_X86_ASM_MACRO(SW_C3, 0x4000);
DEFINE_X86_ASM_MACRO(SW_TOP_7, 0x3800);
DEFINE_X86_ASM_MACRO(SW_TOP_6, 0x3000);
DEFINE_X86_ASM_MACRO(SW_TOP_5, 0x2800);
DEFINE_X86_ASM_MACRO(SW_TOP_4, 0x2000);
DEFINE_X86_ASM_MACRO(SW_TOP_3, 0x1800);
DEFINE_X86_ASM_MACRO(SW_TOP_2, 0x1000);
DEFINE_X86_ASM_MACRO(SW_TOP_1, 0x0800);
DEFINE_X86_ASM_MACRO(SW_TOP_0, 0x0000);
DEFINE_X86_ASM_MACRO(SW_C2, 0x0400);
DEFINE_X86_ASM_MACRO(SW_C1, 0x0200);
DEFINE_X86_ASM_MACRO(SW_C0, 0x0100);
DEFINE_X86_ASM_MACRO(SW_ES, 0x0080);
DEFINE_X86_ASM_MACRO(SW_SF, 0x0040);
DEFINE_X86_ASM_MACRO(SW_PE, 0x0020);
DEFINE_X86_ASM_MACRO(SW_UE, 0x0010);
DEFINE_X86_ASM_MACRO(SW_OE, 0x0008);
DEFINE_X86_ASM_MACRO(SW_ZE, 0x0004);
DEFINE_X86_ASM_MACRO(SW_DE, 0x0002);
DEFINE_X86_ASM_MACRO(SW_IE, 0x0001);
DEFINE_X86_ASM_MACRO(X86_ROUND_CONTROL_MASK, 0x0C00);
DEFINE_X86_ASM_MACRO(X86_PRECISION_CONTROL_MASK, 0x0300);
DEFINE_X86_MACRO(BSUN, 0x00008000);
DEFINE_X86_MACRO(SNAN, 0x00004000);
DEFINE_X86_MACRO(OPERR, 0x00002000);
DEFINE_X86_MACRO(OVFL, 0x00001000);
DEFINE_X86_MACRO(UNFL, 0x00000800);
DEFINE_X86_MACRO(DZ, 0x00000400);
DEFINE_X86_MACRO(INEX2, 0x00000200);
DEFINE_X86_MACRO(INEX1, 0x00000100);
DEFINE_X86_MACRO(ACCR_IOP, 0x80);
DEFINE_X86_MACRO(ACCR_OVFL, 0x40);
DEFINE_X86_MACRO(ACCR_UNFL, 0x20);
DEFINE_X86_MACRO(ACCR_DZ, 0x10);
DEFINE_X86_MACRO(ACCR_INEX, 0x08);
DEFINE_X86_MACRO(ROUND_CONTROL_MASK, 0x30);
DEFINE_X86_MACRO(ROUND_TO_NEAREST, 0);
DEFINE_X86_MACRO(ROUND_TO_ZERO, 0x10);
DEFINE_X86_MACRO(ROUND_TO_NEGATIVE_INFINITY, 0x20);
DEFINE_X86_MACRO(ROUND_TO_POSITIVE_INFINITY, 0x30);
DEFINE_X86_MACRO(PRECISION_CONTROL_MASK, 0xC0);
DEFINE_X86_MACRO(PRECISION_CONTROL_EXTENDED, 0);
DEFINE_X86_MACRO(PRECISION_CONTROL_DOUBLE, 0x80);
DEFINE_X86_MACRO(PRECISION_CONTROL_SINGLE, 0x40);
DEFINE_X86_MACRO(PRECISION_CONTROL_UNDEFINED, 0xC0);
DEFINE_X86_MACRO(CW_RESET, 0x0040);
DEFINE_X86_MACRO(CW_FINIT, 0x037F);
DEFINE_X86_MACRO(SW_RESET, 0x0000);
DEFINE_X86_MACRO(SW_FINIT, 0x0000);
DEFINE_X86_MACRO(TW_RESET, 0x5555);
DEFINE_X86_MACRO(TW_FINIT, 0x0FFF);
DEFINE_X86_MACRO(CW_X, 0x1000);
DEFINE_X86_MACRO(CW_RC_ZERO, 0x0C00);
DEFINE_X86_MACRO(CW_RC_UP, 0x0800);
DEFINE_X86_MACRO(CW_RC_DOWN, 0x0400);
DEFINE_X86_MACRO(CW_RC_NEAR, 0x0000);
DEFINE_X86_MACRO(CW_PC_EXTENDED, 0x0300);
DEFINE_X86_MACRO(CW_PC_DOUBLE, 0x0200);
DEFINE_X86_MACRO(CW_PC_RESERVED, 0x0100);
DEFINE_X86_MACRO(CW_PC_SINGLE, 0x0000);
DEFINE_X86_MACRO(CW_PM, 0x0020);
DEFINE_X86_MACRO(CW_UM, 0x0010);
DEFINE_X86_MACRO(CW_OM, 0x0008);
DEFINE_X86_MACRO(CW_ZM, 0x0004);
DEFINE_X86_MACRO(CW_DM, 0x0002);
DEFINE_X86_MACRO(CW_IM, 0x0001);
DEFINE_X86_MACRO(SW_B, 0x8000);
DEFINE_X86_MACRO(SW_C3, 0x4000);
DEFINE_X86_MACRO(SW_TOP_7, 0x3800);
DEFINE_X86_MACRO(SW_TOP_6, 0x3000);
DEFINE_X86_MACRO(SW_TOP_5, 0x2800);
DEFINE_X86_MACRO(SW_TOP_4, 0x2000);
DEFINE_X86_MACRO(SW_TOP_3, 0x1800);
DEFINE_X86_MACRO(SW_TOP_2, 0x1000);
DEFINE_X86_MACRO(SW_TOP_1, 0x0800);
DEFINE_X86_MACRO(SW_TOP_0, 0x0000);
DEFINE_X86_MACRO(SW_C2, 0x0400);
DEFINE_X86_MACRO(SW_C1, 0x0200);
DEFINE_X86_MACRO(SW_C0, 0x0100);
DEFINE_X86_MACRO(SW_ES, 0x0080);
DEFINE_X86_MACRO(SW_SF, 0x0040);
DEFINE_X86_MACRO(SW_PE, 0x0020);
DEFINE_X86_MACRO(SW_UE, 0x0010);
DEFINE_X86_MACRO(SW_OE, 0x0008);
DEFINE_X86_MACRO(SW_ZE, 0x0004);
DEFINE_X86_MACRO(SW_DE, 0x0002);
DEFINE_X86_MACRO(SW_IE, 0x0001);
DEFINE_X86_MACRO(X86_ROUNDING_MODE, 0x0C00);
DEFINE_X86_MACRO(X86_ROUNDING_PRECISION, 0x0300);
#undef DEFINE_X86_ASM_MACRO
/*
#!/bin/sh
awk=awk
ifile="fpu_x86.h"
ofile="fpu_x86_asm.h"
if [ ! -r "$ifile" ]; then
echo "Error: could not open input file ($ifile)"
exit 1
fi
touch $ofile
if [ $? -ne 0 ]; then
echo "Error: could not open output file ($ofile)"
exit 1
fi
# header
cat > $ofile << EOF
#define DEFINE_X86_ASM_MACRO(name, value) \\
asm(".local " #name "\\n\\t" #name " = " #value)
EOF
# processing with awk
$awk '/#define/ { print "DEFINE_X86_ASM_MACRO(" $2 ", " $3 ");"; }' $ifile >> $ofile
# footer
cat >> $ofile << EOF
#undef DEFINE_X86_ASM_MACRO
EOF
# insert this script
echo "/""*" >> $ofile
cat $0 >> $ofile
echo "*""/" >> $ofile
exit 0
*/
#undef DEFINE_X86_MACRO

View File

@ -0,0 +1,147 @@
/*
* fpu/impl.h - extra functions and inline implementations
*
* Basilisk II (C) 1997-1999 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* 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 FPU_IMPL_H
#define FPU_IMPL_H
/* NOTE: this file shall be included from fpu/core.h */
#undef PUBLIC
#define PUBLIC /**/
#undef PRIVATE
#define PRIVATE /**/
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* -------------------------------------------------------------------------- */
/* --- X86 assembly fpu specific methods --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_X86
/* Return the floating-point status register in m68k format */
PUBLIC inline uae_u32 FFPU get_fpsr(void)
{
return to_m68k_fpcond[(x86_status_word & 0x4700) >> 8]
| FPU fpsr.quotient
| exception_host2mac[x86_status_word & (SW_FAKE_BSUN|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)]
| accrued_exception_host2mac[x86_status_word_accrued & (SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)]
;
}
/* Set the floating-point status register from an m68k format */
PUBLIC inline void FFPU set_fpsr(uae_u32 new_fpsr)
{
x86_status_word = to_host_fpcond[(new_fpsr & FPSR_CCB) >> 24 ]
| exception_mac2host[(new_fpsr & FPSR_EXCEPTION_STATUS) >> 8];
x86_status_word_accrued = accrued_exception_mac2host[(new_fpsr & FPSR_ACCRUED_EXCEPTION) >> 3];
}
#endif
/* -------------------------------------------------------------------------- */
/* --- Original UAE and IEEE FPU core methods --- */
/* -------------------------------------------------------------------------- */
#ifndef FPU_X86
/* Return the floating-point status register in m68k format */
PUBLIC inline uae_u32 FFPU get_fpsr(void)
{
uae_u32 condition_codes = get_fpccr();
uae_u32 exception_status = get_exception_status();
uae_u32 accrued_exception = get_accrued_exception();
uae_u32 quotient = FPU fpsr.quotient;
return (condition_codes | quotient | exception_status | accrued_exception);
}
/* Set the floating-point status register from an m68k format */
PUBLIC inline void FFPU set_fpsr(uae_u32 new_fpsr)
{
set_fpccr ( new_fpsr & FPSR_CCB );
set_exception_status ( new_fpsr & FPSR_EXCEPTION_STATUS );
set_accrued_exception ( new_fpsr & FPSR_ACCRUED_EXCEPTION );
FPU fpsr.quotient = new_fpsr & FPSR_QUOTIENT;
}
#endif
/* -------------------------------------------------------------------------- */
/* --- Common routines for control word --- */
/* -------------------------------------------------------------------------- */
/* Return the floating-point control register in m68k format */
PUBLIC inline uae_u32 FFPU get_fpcr(void)
{
uae_u32 rounding_precision = get_rounding_precision();
uae_u32 rounding_mode = get_rounding_mode();
return (rounding_precision | rounding_mode);
}
/* Set the floating-point control register from an m68k format */
PUBLIC inline void FFPU set_fpcr(uae_u32 new_fpcr)
{
set_rounding_precision ( new_fpcr & FPCR_ROUNDING_PRECISION);
set_rounding_mode ( new_fpcr & FPCR_ROUNDING_MODE );
set_host_control_word();
}
/* -------------------------------------------------------------------------- */
/* --- Specific part to X86 assembly FPU --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_X86
/* Retrieve a floating-point register value and convert it to double precision */
PUBLIC inline double FFPU fpu_get_register(int r)
{
double f;
__asm__ __volatile__("fldt %1\n\tfstpl %0" : "=m" (f) : "m" (FPU registers[r]));
return f;
}
#endif
/* -------------------------------------------------------------------------- */
/* --- Specific to original UAE or new IEEE-based FPU core --- */
/* -------------------------------------------------------------------------- */
#if defined(FPU_UAE) || defined(FPU_IEEE)
/* Retrieve a floating-point register value and convert it to double precision */
PUBLIC inline double FFPU fpu_get_register(int r)
{
return FPU registers[r];
}
#endif
#endif /* FPU_IMPL_H */

View File

@ -0,0 +1,100 @@
/*
* fpu/mathlib.cpp - Floating-point math support library
*
* Basilisk II (C) 1997-2001 Christian Bauer
*
* 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
*
* 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
*/
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */
#undef PRIVATE
#define PRIVATE static
#undef PUBLIC
#define PUBLIC /**/
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
#if defined(FPU_IEEE) && defined(X86_ASSEMBLY)
PRIVATE fpu_extended fp_do_pow(fpu_extended x, fpu_extended y)
{
fpu_extended value, exponent;
uae_s64 p = (uae_s64)y;
if (x == 0.0) {
if (y > 0.0)
return (y == (double) p && (p & 1) != 0 ? x : 0.0);
else if (y < 0.0)
return (y == (double) p && (-p & 1) != 0 ? 1.0 / x : 1.0 / fp_fabs (x));
}
if (y == (double) p) {
fpu_extended r = 1.0;
if (p == 0)
return 1.0;
if (p < 0) {
p = -p;
x = 1.0 / x;
}
while (1) {
if (p & 1)
r *= x;
p >>= 1;
if (p == 0)
return r;
x *= x;
}
}
__asm__ __volatile__("fyl2x" : "=t" (value) : "0" (x), "u" (1.0) : "st(1)");
__asm__ __volatile__("fmul %%st(1) # y * log2(x)\n\t"
"fst %%st(1)\n\t"
"frndint # int(y * log2(x))\n\t"
"fxch\n\t"
"fsub %%st(1) # fract(y * log2(x))\n\t"
"f2xm1 # 2^(fract(y * log2(x))) - 1\n\t"
: "=t" (value), "=u" (exponent) : "0" (y), "1" (value));
value += 1.0;
__asm__ __volatile__("fscale" : "=t" (value) : "0" (value), "u" (exponent));
return value;
}
PRIVATE fpu_extended fp_do_log1p(fpu_extended x)
{
// TODO: handle NaN and +inf/-inf
fpu_extended value;
// The fyl2xp1 can only be used for values in
// -1 + sqrt(2) / 2 <= x <= 1 - sqrt(2) / 2
// 0.29 is a safe value.
if (fp_fabs(x) <= 0.29)
__asm__ __volatile__("fldln2; fxch; fyl2xp1" : "=t" (value) : "0" (x));
else
__asm__ __volatile__("fldln2; fxch; fyl2x" : "=t" (value) : "0" (x + 1.0));
return value;
}
#endif

View File

@ -0,0 +1,992 @@
/*
* fpu/mathlib.h - Floating-point math support library
*
* Basilisk II (C) 1997-2001 Christian Bauer
*
* 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
*
* 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 FPU_MATHLIB_H
#define FPU_MATHLIB_H
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */
#undef PUBLIC
#define PUBLIC extern
#undef PRIVATE
#define PRIVATE static
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
// Define the following macro if branches are expensive. If so,
// integer-based isnan() and isinf() functions are implemented.
// TODO: move to Makefile.in
#define BRANCHES_ARE_EXPENSIVE 1
// Use ISO C99 extended-precision math functions (glibc 2.1+)
#define FPU_USE_ISO_C99 1
// NOTE: this is irrelevant on Win32 platforms since the MS libraries
// don't support extended-precision floating-point computations
#ifdef WIN32
#undef FPU_USE_ISO_C99
#endif
// Use faster implementation of math functions, but this could cause
// some incorrect results (?)
// TODO: actually implement the slower but safer versions
#define FPU_FAST_MATH 1
#if FPU_USE_ISO_C99
// NOTE: no prior <math.h> shall be included at this point
#define __USE_ISOC99 1 // for glibc 2.2.X and newer
#define __USE_ISOC9X 1 // for glibc 2.1.X
#include <math.h>
#else
#include <cmath>
using namespace std;
#endif
/* -------------------------------------------------------------------------- */
/* --- Floating-point register types --- */
/* -------------------------------------------------------------------------- */
// Single : S 8*E 23*F
#define FP_SINGLE_EXP_MAX 0xff
#define FP_SINGLE_EXP_BIAS 0x7f
// Double : S 11*E 52*F
#define FP_DOUBLE_EXP_MAX 0x7ff
#define FP_DOUBLE_EXP_BIAS 0x3ff
// Extended : S 15*E 64*F
#define FP_EXTENDED_EXP_MAX 0x7fff
#define FP_EXTENDED_EXP_BIAS 0x3fff
// Zeroes : E = 0 & F = 0
// Infinities : E = MAX & F = 0
// Not-A-Number : E = MAX & F # 0
/* -------------------------------------------------------------------------- */
/* --- Floating-point type shapes (IEEE-compliant) --- */
/* -------------------------------------------------------------------------- */
// Taken from glibc 2.2.x: ieee754.h
// IEEE-754 float format
union fpu_single_shape {
fpu_single value;
/* This is the IEEE 754 single-precision format. */
struct {
#if UAE_BYTE_ORDER == UAE_BIG_ENDIAN
unsigned int negative:1;
unsigned int exponent:8;
unsigned int mantissa:23;
#endif /* Big endian. */
#if UAE_BYTE_ORDER == UAE_LITTLE_ENDIAN
unsigned int mantissa:23;
unsigned int exponent:8;
unsigned int negative:1;
#endif /* Little endian. */
} ieee;
/* This format makes it easier to see if a NaN is a signalling NaN. */
struct {
#if UAE_BYTE_ORDER == UAE_BIG_ENDIAN
unsigned int negative:1;
unsigned int exponent:8;
unsigned int quiet_nan:1;
unsigned int mantissa:22;
#endif /* Big endian. */
#if UAE_BYTE_ORDER == UAE_LITTLE_ENDIAN
unsigned int mantissa:22;
unsigned int quiet_nan:1;
unsigned int exponent:8;
unsigned int negative:1;
#endif /* Little endian. */
} ieee_nan;
};
// IEEE-754 double format
union fpu_double_shape {
fpu_double value;
/* This is the IEEE 754 double-precision format. */
struct {
#if UAE_BYTE_ORDER == UAE_BIG_ENDIAN
unsigned int negative:1;
unsigned int exponent:11;
/* Together these comprise the mantissa. */
unsigned int mantissa0:20;
unsigned int mantissa1:32;
#endif /* Big endian. */
#if UAE_BYTE_ORDER == UAE_LITTLE_ENDIAN
# if UAE_FLOAT_WORD_ORDER == UAE_BIG_ENDIAN
unsigned int mantissa0:20;
unsigned int exponent:11;
unsigned int negative:1;
unsigned int mantissa1:32;
# else
/* Together these comprise the mantissa. */
unsigned int mantissa1:32;
unsigned int mantissa0:20;
unsigned int exponent:11;
unsigned int negative:1;
# endif
#endif /* Little endian. */
} ieee;
/* This format makes it easier to see if a NaN is a signalling NaN. */
struct {
#if UAE_BYTE_ORDER == UAE_BIG_ENDIAN
unsigned int negative:1;
unsigned int exponent:11;
unsigned int quiet_nan:1;
/* Together these comprise the mantissa. */
unsigned int mantissa0:19;
unsigned int mantissa1:32;
#else
# if UAE_FLOAT_WORD_ORDER == UAE_BIG_ENDIAN
unsigned int mantissa0:19;
unsigned int quiet_nan:1;
unsigned int exponent:11;
unsigned int negative:1;
unsigned int mantissa1:32;
# else
/* Together these comprise the mantissa. */
unsigned int mantissa1:32;
unsigned int mantissa0:19;
unsigned int quiet_nan:1;
unsigned int exponent:11;
unsigned int negative:1;
# endif
#endif
} ieee_nan;
};
#if SIZEOF_LONG_DOUBLE == 12
# undef USE_QUAD_DOUBLE
#elif SIZEOF_LONG_DOUBLE == 16
# define USE_QUAD_DOUBLE
#else
# error "unsupported long double format"
#endif
#ifndef USE_QUAD_DOUBLE
// IEEE-854 long double format
union fpu_extended_shape {
fpu_extended value;
/* This is the IEEE 854 double-extended-precision format. */
struct {
#if UAE_BYTE_ORDER == UAE_BIG_ENDIAN
unsigned int negative:1;
unsigned int exponent:15;
unsigned int empty:16;
unsigned int mantissa0:32;
unsigned int mantissa1:32;
#endif
#if UAE_BYTE_ORDER == UAE_LITTLE_ENDIAN
# if UAE_FLOAT_WORD_ORDER == UAE_BIG_ENDIAN
unsigned int exponent:15;
unsigned int negative:1;
unsigned int empty:16;
unsigned int mantissa0:32;
unsigned int mantissa1:32;
# else
unsigned int mantissa1:32;
unsigned int mantissa0:32;
unsigned int exponent:15;
unsigned int negative:1;
unsigned int empty:16;
# endif
#endif
} ieee;
/* This is for NaNs in the IEEE 854 double-extended-precision format. */
struct {
#if UAE_BYTE_ORDER == UAE_BIG_ENDIAN
unsigned int negative:1;
unsigned int exponent:15;
unsigned int empty:16;
unsigned int one:1;
unsigned int quiet_nan:1;
unsigned int mantissa0:30;
unsigned int mantissa1:32;
#endif
#if UAE_BYTE_ORDER == UAE_LITTLE_ENDIAN
# if UAE_FLOAT_WORD_ORDER == UAE_BIG_ENDIAN
unsigned int exponent:15;
unsigned int negative:1;
unsigned int empty:16;
unsigned int mantissa0:30;
unsigned int quiet_nan:1;
unsigned int one:1;
unsigned int mantissa1:32;
# else
unsigned int mantissa1:32;
unsigned int mantissa0:30;
unsigned int quiet_nan:1;
unsigned int one:1;
unsigned int exponent:15;
unsigned int negative:1;
unsigned int empty:16;
# endif
#endif
} ieee_nan;
/* This format is used to extract the sign_exponent and mantissa parts only */
struct {
#if UAE_FLOAT_WORD_ORDER == UAE_BIG_ENDIAN
unsigned int sign_exponent:16;
unsigned int empty:16;
unsigned int msw:32;
unsigned int lsw:32;
#else
unsigned int lsw:32;
unsigned int msw:32;
unsigned int sign_exponent:16;
unsigned int empty:16;
#endif
} parts;
};
#else
// IEEE-854 quad double format
union fpu_extended_shape {
fpu_extended value;
/* This is the IEEE 854 quad-precision format. */
struct {
#if UAE_BYTE_ORDER == UAE_BIG_ENDIAN
unsigned int negative:1;
unsigned int exponent:15;
unsigned int mantissa0:16;
unsigned int mantissa1:32;
unsigned int mantissa2:32;
unsigned int mantissa3:32;
#else
unsigned int mantissa3:32;
unsigned int mantissa2:32;
unsigned int mantissa1:32;
unsigned int mantissa0:16;
unsigned int exponent:15;
unsigned int negative:1;
#endif
} ieee;
/* This is for NaNs in the IEEE 854 quad-precision format. */
struct {
#if UAE_BYTE_ORDER == UAE_BIG_ENDIAN
unsigned int negative:1;
unsigned int exponent:15;
unsigned int quiet_nan:1;
unsigned int mantissa0:15;
unsigned int mantissa1:30;
unsigned int mantissa2:32;
unsigned int mantissa3:32;
#else
unsigned int mantissa3:32;
unsigned int mantissa2:32;
unsigned int mantissa1:32;
unsigned int mantissa0:15;
unsigned int quiet_nan:1;
unsigned int exponent:15;
unsigned int negative:1;
#endif
} ieee_nan;
/* This format is used to extract the sign_exponent and mantissa parts only */
#if UAE_FLOAT_WORD_ORDER == UAE_BIG_ENDIAN
struct {
uae_u64 msw;
uae_u64 lsw;
} parts64;
struct {
uae_u32 w0;
uae_u32 w1;
uae_u32 w2;
uae_u32 w3;
} parts32;
#else
struct {
uae_u64 lsw;
uae_u64 msw;
} parts64;
struct {
uae_u32 w3;
uae_u32 w2;
uae_u32 w1;
uae_u32 w0;
} parts32;
#endif
};
#endif // !USE_QUAD_DOUBLE
// Declare and initialize a pointer to a shape of the requested FP type
#define fp_declare_init_shape(psvar, rfvar, ftype) \
fpu_ ## ftype ## _shape * psvar = (fpu_ ## ftype ## _shape *)( &rfvar )
/* -------------------------------------------------------------------------- */
/* --- Extra Math Functions --- */
/* --- (most of them had to be defined before including <fpu/flags.h>) --- */
/* -------------------------------------------------------------------------- */
#undef isnan
#if 0 && defined(HAVE_ISNANL)
# define isnan(x) isnanl((x))
#else
# define isnan(x) fp_do_isnan((x))
#endif
PRIVATE inline bool FFPU fp_do_isnan(fpu_register const & r)
{
fp_declare_init_shape(sxp, r, extended);
#ifdef BRANCHES_ARE_EXPENSIVE
#ifdef USE_QUAD_DOUBLE
uae_s64 hx = sxp->parts64.msw;
uae_s64 lx = sxp->parts64.lsw;
hx &= 0x7fffffffffffffffLL;
hx |= (uae_u64)(lx | (-lx)) >> 63;
hx = 0x7fff000000000000LL - hx;
return (int)((uae_u64)hx >> 63);
#else
uae_s32 se = sxp->parts.sign_exponent;
uae_s32 hx = sxp->parts.msw;
uae_s32 lx = sxp->parts.lsw;
se = (se & 0x7fff) << 1;
lx |= hx & 0x7fffffff;
se |= (uae_u32)(lx | (-lx)) >> 31;
se = 0xfffe - se;
// TODO: check whether rshift count is 16 or 31
return (int)(((uae_u32)(se)) >> 16);
#endif
#else
return (sxp->ieee_nan.exponent == FP_EXTENDED_EXP_MAX)
&& (sxp->ieee_nan.mantissa0 != 0)
&& (sxp->ieee_nan.mantissa1 != 0)
#ifdef USE_QUAD_DOUBLE
&& (sxp->ieee_nan.mantissa2 != 0)
&& (sxp->ieee_nan.mantissa3 != 0)
#endif
;
#endif
}
#undef isinf
#if 0 && defined(HAVE_ISINFL)
# define isinf(x) isinfl((x))
#else
# define isinf(x) fp_do_isinf((x))
#endif
PRIVATE inline bool FFPU fp_do_isinf(fpu_register const & r)
{
fp_declare_init_shape(sxp, r, extended);
#ifdef BRANCHES_ARE_EXPENSIVE
#ifdef USE_QUAD_DOUBLE
uae_s64 hx = sxp->parts64.msw;
uae_s64 lx = sxp->parts64.lsw;
lx |= (hx & 0x7fffffffffffffffLL) ^ 0x7fff000000000000LL;
lx |= -lx;
return ~(lx >> 63) & (hx >> 62);
#else
uae_s32 se = sxp->parts.sign_exponent;
uae_s32 hx = sxp->parts.msw;
uae_s32 lx = sxp->parts.lsw;
/* This additional ^ 0x80000000 is necessary because in Intel's
internal representation of the implicit one is explicit.
NOTE: anyway, this is equivalent to & 0x7fffffff in that case. */
#ifdef __i386__
lx |= (hx ^ 0x80000000) | ((se & 0x7fff) ^ 0x7fff);
#else
lx |= (hx & 0x7fffffff) | ((se & 0x7fff) ^ 0x7fff);
#endif
lx |= -lx;
se &= 0x8000;
return ~(lx >> 31) & (1 - (se >> 14));
#endif
#else
return (sxp->ieee_nan.exponent == FP_EXTENDED_EXP_MAX)
&& (sxp->ieee_nan.mantissa0 == 0)
&& (sxp->ieee_nan.mantissa1 == 0)
#ifdef USE_QUAD_DOUBLE
&& (sxp->ieee_nan.mantissa2 == 0)
&& (sxp->ieee_nan.mantissa3 == 0)
#endif
;
#endif
}
#undef isneg
#define isneg(x) fp_do_isneg((x))
PRIVATE inline bool FFPU fp_do_isneg(fpu_register const & r)
{
fp_declare_init_shape(sxp, r, extended);
return (sxp->ieee.negative)
;
}
#undef iszero
#define iszero(x) fp_do_iszero((x))
PRIVATE inline bool FFPU fp_do_iszero(fpu_register const & r)
{
// TODO: BRANCHES_ARE_EXPENSIVE
fp_declare_init_shape(sxp, r, extended);
return (sxp->ieee.exponent == 0)
&& (sxp->ieee.mantissa0 == 0)
&& (sxp->ieee.mantissa1 == 0)
#ifdef USE_QUAD_DOUBLE
&& (sxp->ieee.mantissa2 == 0)
&& (sxp->ieee.mantissa3 == 0)
#endif
;
}
PRIVATE inline void FFPU get_dest_flags(fpu_register const & r)
{
fl_dest.negative = isneg(r);
fl_dest.zero = iszero(r);
fl_dest.infinity = isinf(r);
fl_dest.nan = isnan(r);
fl_dest.in_range = !fl_dest.zero && !fl_dest.infinity && !fl_dest.nan;
}
PRIVATE inline void FFPU get_source_flags(fpu_register const & r)
{
fl_source.negative = isneg(r);
fl_source.zero = iszero(r);
fl_source.infinity = isinf(r);
fl_source.nan = isnan(r);
fl_source.in_range = !fl_source.zero && !fl_source.infinity && !fl_source.nan;
}
PRIVATE inline void FFPU make_nan(fpu_register & r)
{
// FIXME: is that correct ?
fp_declare_init_shape(sxp, r, extended);
sxp->ieee.exponent = FP_EXTENDED_EXP_MAX;
sxp->ieee.mantissa0 = 0xffffffff;
sxp->ieee.mantissa1 = 0xffffffff;
#ifdef USE_QUAD_DOUBLE
sxp->ieee.mantissa2 = 0xffffffff;
sxp->ieee.mantissa3 = 0xffffffff;
#endif
}
PRIVATE inline void FFPU make_zero_positive(fpu_register & r)
{
#if 1
r = +0.0;
#else
fp_declare_init_shape(sxp, r, extended);
sxp->ieee.negative = 0;
sxp->ieee.exponent = 0;
sxp->ieee.mantissa0 = 0;
sxp->ieee.mantissa1 = 0;
#ifdef USE_QUAD_DOUBLE
sxp->ieee.mantissa2 = 0;
sxp->ieee.mantissa3 = 0;
#endif
#endif
}
PRIVATE inline void FFPU make_zero_negative(fpu_register & r)
{
#if 1
r = -0.0;
#else
fp_declare_init_shape(sxp, r, extended);
sxp->ieee.negative = 1;
sxp->ieee.exponent = 0;
sxp->ieee.mantissa0 = 0;
sxp->ieee.mantissa1 = 0;
#ifdef USE_QUAD_DOUBLE
sxp->ieee.mantissa2 = 0;
sxp->ieee.mantissa3 = 0;
#endif
#endif
}
PRIVATE inline void FFPU make_inf_positive(fpu_register & r)
{
fp_declare_init_shape(sxp, r, extended);
sxp->ieee_nan.negative = 0;
sxp->ieee_nan.exponent = FP_EXTENDED_EXP_MAX;
sxp->ieee_nan.mantissa0 = 0;
sxp->ieee_nan.mantissa1 = 0;
#ifdef USE_QUAD_DOUBLE
sxp->ieee_nan.mantissa2 = 0;
sxp->ieee_nan.mantissa3 = 0;
#endif
}
PRIVATE inline void FFPU make_inf_negative(fpu_register & r)
{
fp_declare_init_shape(sxp, r, extended);
sxp->ieee_nan.negative = 1;
sxp->ieee_nan.exponent = FP_EXTENDED_EXP_MAX;
sxp->ieee_nan.mantissa0 = 0;
sxp->ieee_nan.mantissa1 = 0;
#ifdef USE_QUAD_DOUBLE
sxp->ieee_nan.mantissa2 = 0;
sxp->ieee_nan.mantissa3 = 0;
#endif
}
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add)
{
fp_declare_init_shape(sxp, r, extended);
// TODO: overflow flags
int exp = sxp->ieee.exponent + add;
// FIXME: this test is not correct: see fpuop_fscale()
if (exp > FP_EXTENDED_EXP_BIAS) {
make_inf_positive(r);
} else if (exp < 0) {
// keep sign (+/- 0)
if (isneg(r))
make_inf_negative(r);
else
make_inf_positive(r);
// p[FHI] &= 0x80000000;
} else {
sxp->ieee.exponent = exp;
// p[FHI] = (p[FHI] & 0x800FFFFF) | ((uae_u32)exp << 20);
}
}
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r)
{
fp_declare_init_shape(sxp, r, extended);
return (sxp->ieee.exponent - FP_EXTENDED_EXP_BIAS);
}
// Normalize to range 1..2
PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r)
{
fp_declare_init_shape(sxp, r, extended);
sxp->ieee.exponent = FP_EXTENDED_EXP_BIAS;
}
// The sign of the quotient is the exclusive-OR of the sign bits
// of the source and destination operands.
PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_register const & rb)
{
fp_declare_init_shape(sap, ra, extended);
fp_declare_init_shape(sbp, rb, extended);
return (((sap->ieee.mantissa0 ^ sbp->ieee.mantissa0) & 0x80000000) ? 0x800000 : 0);
}
/* -------------------------------------------------------------------------- */
/* --- Math functions --- */
/* -------------------------------------------------------------------------- */
#if FPU_USE_ISO_C99
# define fp_log logl
# define fp_log10 log10l
# define fp_exp expl
# define fp_pow powl
# define fp_fabs fabsl
# define fp_sqrt sqrtl
# define fp_sin sinl
# define fp_cos cosl
# define fp_tan tanl
# define fp_sinh sinhl
# define fp_cosh coshl
# define fp_tanh tanhl
# define fp_asin asinl
# define fp_acos acosl
# define fp_atan atanl
# define fp_asinh asinhl
# define fp_acosh acoshl
# define fp_atanh atanhl
# define fp_floor floorl
# define fp_ceil ceill
#else
# define fp_log log
# define fp_log10 log10
# define fp_exp exp
# define fp_pow pow
# define fp_fabs fabs
# define fp_sqrt sqrt
# define fp_sin sin
# define fp_cos cos
# define fp_tan tan
# define fp_sinh sinh
# define fp_cosh cosh
# define fp_tanh tanh
# define fp_asin asin
# define fp_acos acos
# define fp_atan atan
# define fp_asinh asinh
# define fp_acosh acosh
# define fp_atanh atanh
# define fp_floor floor
# define fp_ceil ceil
#endif
#if defined(FPU_IEEE) && defined(X86_ASSEMBLY)
// Assembly optimized support functions. Taken from glibc 2.2.2
#undef fp_log
#define fp_log fp_do_log
#ifndef FPU_FAST_MATH
// FIXME: unimplemented
PRIVATE fpu_extended fp_do_log(fpu_extended x);
#else
PRIVATE inline fpu_extended fp_do_log(fpu_extended x)
{
fpu_extended value;
__asm__ __volatile__("fldln2; fxch; fyl2x" : "=t" (value) : "0" (x) : "st(1)");
return value;
}
#endif
#undef fp_log10
#define fp_log10 fp_do_log10
#ifndef FPU_FAST_MATH
// FIXME: unimplemented
PRIVATE fpu_extended fp_do_log10(fpu_extended x);
#else
PRIVATE inline fpu_extended fp_do_log10(fpu_extended x)
{
fpu_extended value;
__asm__ __volatile__("fldlg2; fxch; fyl2x" : "=t" (value) : "0" (x) : "st(1)");
return value;
}
#endif
#undef fp_exp
#define fp_exp fp_do_exp
#ifndef FPU_FAST_MATH
// FIXME: unimplemented
PRIVATE fpu_extended fp_do_exp(fpu_extended x);
#else
PRIVATE inline fpu_extended fp_do_exp(fpu_extended x)
{
fpu_extended value, exponent;
__asm__ __volatile__("fldl2e # e^x = 2^(x * log2(e))\n\t"
"fmul %%st(1) # x * log2(e)\n\t"
"fst %%st(1)\n\t"
"frndint # int(x * log2(e))\n\t"
"fxch\n\t"
"fsub %%st(1) # fract(x * log2(e))\n\t"
"f2xm1 # 2^(fract(x * log2(e))) - 1\n\t"
: "=t" (value), "=u" (exponent) : "0" (x));
value += 1.0;
__asm__ __volatile__("fscale" : "=t" (value) : "0" (value), "u" (exponent));
return value;
}
#endif
#undef fp_pow
#define fp_pow fp_do_pow
PRIVATE fpu_extended fp_do_pow(fpu_extended x, fpu_extended y);
#undef fp_fabs
#define fp_fabs fp_do_fabs
PRIVATE inline fpu_extended fp_do_fabs(fpu_extended x)
{
fpu_extended value;
__asm__ __volatile__("fabs" : "=t" (value) : "0" (x));
return value;
}
#undef fp_sqrt
#define fp_sqrt fp_do_sqrt
PRIVATE inline fpu_extended fp_do_sqrt(fpu_extended x)
{
fpu_extended value;
__asm__ __volatile__("fsqrt" : "=t" (value) : "0" (x));
return value;
}
#undef fp_sin
#define fp_sin fp_do_sin
PRIVATE inline fpu_extended fp_do_sin(fpu_extended x)
{
fpu_extended value;
__asm__ __volatile__("fsin" : "=t" (value) : "0" (x));
return value;
}
#undef fp_cos
#define fp_cos fp_do_cos
PRIVATE inline fpu_extended fp_do_cos(fpu_extended x)
{
fpu_extended value;
__asm__ __volatile__("fcos" : "=t" (value) : "0" (x));
return value;
}
#undef fp_tan
#define fp_tan fp_do_tan
PRIVATE inline fpu_extended fp_do_tan(fpu_extended x)
{
fpu_extended value;
__asm__ __volatile__("fptan" : "=t" (value) : "0" (x));
return value;
}
#undef fp_expm1
#define fp_expm1 fp_do_expm1
// Returns: exp(X) - 1.0
PRIVATE inline fpu_extended fp_do_expm1(fpu_extended x)
{
fpu_extended value, exponent, temp;
__asm__ __volatile__("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t"
"fmul %%st(1) # x * log2(e)\n\t"
"fst %%st(1)\n\t"
"frndint # int(x * log2(e))\n\t"
"fxch\n\t"
"fsub %%st(1) # fract(x * log2(e))\n\t"
"f2xm1 # 2^(fract(x * log2(e))) - 1\n\t"
"fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t"
: "=t" (value), "=u" (exponent) : "0" (x));
__asm__ __volatile__("fscale" : "=t" (temp) : "0" (1.0), "u" (exponent));
temp -= 1.0;
return temp + value ? temp + value : x;
}
#undef fp_sgn1
#define fp_sgn1 fp_do_sgn1
PRIVATE inline fpu_extended fp_do_sgn1(fpu_extended x)
{
fp_declare_init_shape(sxp, x, extended);
sxp->ieee_nan.exponent = FP_EXTENDED_EXP_MAX;
sxp->ieee_nan.one = 1;
sxp->ieee_nan.quiet_nan = 0;
sxp->ieee_nan.mantissa0 = 0;
sxp->ieee_nan.mantissa1 = 0;
return x;
}
#undef fp_sinh
#define fp_sinh fp_do_sinh
#ifndef FPU_FAST_MATH
// FIXME: unimplemented
PRIVATE fpu_extended fp_do_sinh(fpu_extended x);
#else
PRIVATE inline fpu_extended fp_do_sinh(fpu_extended x)
{
fpu_extended exm1 = fp_expm1(fp_fabs(x));
return 0.5 * (exm1 / (exm1 + 1.0) + exm1) * fp_sgn1(x);
}
#endif
#undef fp_cosh
#define fp_cosh fp_do_cosh
#ifndef FPU_FAST_MATH
// FIXME: unimplemented
PRIVATE fpu_extended fp_do_cosh(fpu_extended x);
#else
PRIVATE inline fpu_extended fp_do_cosh(fpu_extended x)
{
fpu_extended ex = fp_exp(x);
return 0.5 * (ex + 1.0 / ex);
}
#endif
#undef fp_tanh
#define fp_tanh fp_do_tanh
#ifndef FPU_FAST_MATH
// FIXME: unimplemented
PRIVATE fpu_extended fp_do_tanh(fpu_extended x);
#else
PRIVATE inline fpu_extended fp_do_tanh(fpu_extended x)
{
fpu_extended exm1 = fp_expm1(-fp_fabs(x + x));
return exm1 / (exm1 + 2.0) * fp_sgn1(-x);
}
#endif
#undef fp_atan2
#define fp_atan2 fp_do_atan2
PRIVATE inline fpu_extended fp_do_atan2(fpu_extended y, fpu_extended x)
{
fpu_extended value;
__asm__ __volatile__("fpatan" : "=t" (value) : "0" (x), "u" (y) : "st(1)");
return value;
}
#undef fp_asin
#define fp_asin fp_do_asin
PRIVATE inline fpu_extended fp_do_asin(fpu_extended x)
{
return fp_atan2(x, fp_sqrt(1.0 - x * x));
}
#undef fp_acos
#define fp_acos fp_do_acos
PRIVATE inline fpu_extended fp_do_acos(fpu_extended x)
{
return fp_atan2(fp_sqrt(1.0 - x * x), x);
}
#undef fp_atan
#define fp_atan fp_do_atan
PRIVATE inline fpu_extended fp_do_atan(fpu_extended x)
{
fpu_extended value;
__asm__ __volatile__("fld1; fpatan" : "=t" (value) : "0" (x) : "st(1)");
return value;
}
#undef fp_log1p
#define fp_log1p fp_do_log1p
// Returns: ln(1.0 + X)
PRIVATE fpu_extended fp_do_log1p(fpu_extended x);
#undef fp_asinh
#define fp_asinh fp_do_asinh
PRIVATE inline fpu_extended fp_do_asinh(fpu_extended x)
{
fpu_extended y = fp_fabs(x);
return (fp_log1p(y * y / (fp_sqrt(y * y + 1.0) + 1.0) + y) * fp_sgn1(x));
}
#undef fp_acosh
#define fp_acosh fp_do_acosh
PRIVATE inline fpu_extended fp_do_acosh(fpu_extended x)
{
return fp_log(x + fp_sqrt(x - 1.0) * fp_sqrt(x + 1.0));
}
#undef fp_atanh
#define fp_atanh fp_do_atanh
PRIVATE inline fpu_extended fp_do_atanh(fpu_extended x)
{
fpu_extended y = fp_fabs(x);
return -0.5 * fp_log1p(-(y + y) / (1.0 + y)) * fp_sgn1(x);
}
#undef fp_floor
#define fp_floor fp_do_floor
PRIVATE inline fpu_extended fp_do_floor(fpu_extended x)
{
volatile unsigned int cw;
__asm__ __volatile__("fnstcw %0" : "=m" (cw));
volatile unsigned int cw_temp = (cw & 0xf3ff) | 0x0400; // rounding down
__asm__ __volatile__("fldcw %0" : : "m" (cw_temp));
fpu_extended value;
__asm__ __volatile__("frndint" : "=t" (value) : "0" (x));
__asm__ __volatile__("fldcw %0" : : "m" (cw));
return value;
}
#undef fp_ceil
#define fp_ceil fp_do_ceil
PRIVATE inline fpu_extended fp_do_ceil(fpu_extended x)
{
volatile unsigned int cw;
__asm__ __volatile__("fnstcw %0" : "=m" (cw));
volatile unsigned int cw_temp = (cw & 0xf3ff) | 0x0800; // rounding up
__asm__ __volatile__("fldcw %0" : : "m" (cw_temp));
fpu_extended value;
__asm__ __volatile__("frndint" : "=t" (value) : "0" (x));
__asm__ __volatile__("fldcw %0" : : "m" (cw));
return value;
}
#define DEFINE_ROUND_FUNC(rounding_mode_str, rounding_mode) \
PRIVATE inline fpu_extended fp_do_round_to_ ## rounding_mode_str(fpu_extended x) \
{ \
volatile unsigned int cw; \
__asm__ __volatile__("fnstcw %0" : "=m" (cw)); \
volatile unsigned int cw_temp = (cw & 0xf3ff) | (rounding_mode); \
__asm__ __volatile__("fldcw %0" : : "m" (cw_temp)); \
fpu_extended value; \
__asm__ __volatile__("frndint" : "=t" (value) : "0" (x)); \
__asm__ __volatile__("fldcw %0" : : "m" (cw)); \
return value; \
}
#undef fp_round_to_minus_infinity
#define fp_round_to_minus_infinity fp_do_round_to_minus_infinity
DEFINE_ROUND_FUNC(minus_infinity, 0x400)
#undef fp_round_to_plus_infinity
#define fp_round_to_plus_infinity fp_do_round_to_plus_infinity
DEFINE_ROUND_FUNC(plus_infinity, 0x800)
#undef fp_round_to_zero
#define fp_round_to_zero fp_do_round_to_zero
DEFINE_ROUND_FUNC(zero, 0xc00)
#undef fp_round_to_nearest
#define fp_round_to_nearest fp_do_round_to_nearest
DEFINE_ROUND_FUNC(nearest, 0x000)
#endif /* X86_ASSEMBLY */
#ifndef fp_round_to_minus_infinity
#define fp_round_to_minus_infinity(x) fp_floor(x)
#endif
#ifndef fp_round_to_plus_infinity
#define fp_round_to_plus_infinity(x) fp_ceil(x)
#endif
#ifndef fp_round_to_zero
#define fp_round_to_zero(x) ((int)(x))
#endif
#ifndef fp_round_to_nearest
#define fp_round_to_nearest(x) ((int)((x) + 0.5))
#endif
#endif /* FPU_MATHLIB_H */

View File

@ -0,0 +1,64 @@
/*
* fpu/rounding.cpp - system-dependant FPU rounding mode and precision
*
* Basilisk II (C) 1997-1999 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* 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
*/
#undef PRIVATE
#define PRIVATE /**/
#undef PUBLIC
#define PUBLIC /**/
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* -------------------------------------------------------------------------- */
/* --- Native X86 Rounding Mode --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_X86_ROUNDING_MODE
const uae_u32 FFPU x86_control_word_rm_mac2host[] = {
CW_RC_NEAR,
CW_RC_ZERO,
CW_RC_DOWN,
CW_RC_UP
};
#endif
/* -------------------------------------------------------------------------- */
/* --- Native X86 Rounding Precision --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_X86_ROUNDING_PRECISION
const uae_u32 FFPU x86_control_word_rp_mac2host[] = {
CW_PC_EXTENDED,
CW_PC_SINGLE,
CW_PC_DOUBLE,
CW_PC_RESERVED
};
#endif

View File

@ -0,0 +1,154 @@
/*
* fpu/rounding.h - system-dependant FPU rounding mode and precision
*
* Basilisk II (C) 1997-1999 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* 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 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(X86_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(X86_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(X86_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(X86_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 */
PUBLIC inline uae_u32 FFPU get_rounding_mode(void)
{ return FPU fpcr.rounding_mode; }
/* Convert and set to native rounding mode */
PUBLIC 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 */
PUBLIC inline uae_u32 FFPU get_rounding_precision(void)
{ return FPU fpcr.rounding_precision; }
/* Convert and set to native rounding precision */
PUBLIC inline void FFPU set_rounding_precision(uae_u32 new_rounding_precision)
{ FPU fpcr.rounding_precision = new_rounding_precision; }
#endif
#endif /* FPU_ROUNDING_H */

View File

@ -0,0 +1,148 @@
/*
* types.h - basic types for fpu registers
*
* Basilisk II (C) 1997-1999 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* 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 FPU_TYPES_H
#define FPU_TYPES_H
#include "sysdeps.h"
/* Default behavior is *not* to use long doubles */
#define USE_LONG_DOUBLE 0
/* -------------------------------------------------------------------------- */
/* --- Original UAE fpu core --- */
/* -------------------------------------------------------------------------- */
#if defined(FPU_UAE)
/* 4-byte floats */
#if SIZEOF_FLOAT == 4
typedef float uae_f32;
#elif SIZEOF_DOUBLE == 4
typedef double uae_f32;
#else
#error "No 4 byte float type, you lose."
#endif
/* 8-byte floats */
#if SIZEOF_DOUBLE == 8
typedef double uae_f64;
#elif SIZEOF_LONG_DOUBLE == 8
typedef long double uae_f64;
#else
#error "No 8 byte float type, you lose."
#endif
/* Original UAE FPU registers are only 8 bytes long */
typedef uae_f64 fpu_register;
typedef fpu_register fpu_extended;
typedef uae_f64 fpu_double;
typedef uae_f32 fpu_single;
/* -------------------------------------------------------------------------- */
/* --- Optimized core for x86 --- */
/* -------------------------------------------------------------------------- */
#elif defined(FPU_X86)
/* 4-byte floats */
#if SIZEOF_FLOAT == 4
typedef float uae_f32;
#elif SIZEOF_DOUBLE == 4
typedef double uae_f32;
#else
#error "No 4 byte float type, you lose."
#endif
/* 8-byte floats */
#if SIZEOF_DOUBLE == 8
typedef float uae_f64;
#elif SIZEOF_LONG_DOUBLE == 8
typedef double uae_f64;
#else
#error "No 8 byte float type, you lose."
#endif
/* At least 10-byte floats are required */
#if SIZEOF_LONG_DOUBLE >= 10
typedef long double fpu_register;
#else
#error "No float type at least 10 bytes long, you lose."
#endif
/* X86 FPU has a custom register type that maps to a native X86 register */
typedef fpu_register fpu_extended;
typedef uae_f64 fpu_double;
typedef uae_f32 fpu_single;
/* -------------------------------------------------------------------------- */
/* --- C99 implementation --- */
/* -------------------------------------------------------------------------- */
#elif defined(FPU_IEEE)
/* 4-byte floats */
#if SIZEOF_FLOAT == 4
typedef float uae_f32;
#elif SIZEOF_DOUBLE == 4
typedef double uae_f32;
#else
#error "No 4 byte float type, you lose."
#endif
/* 8-byte floats */
#if SIZEOF_DOUBLE == 8
typedef double uae_f64;
#elif SIZEOF_LONG_DOUBLE == 8
typedef long double uae_f64;
#else
#error "No 8 byte float type, you lose."
#endif
/* 12-byte or 16-byte floats */
#if SIZEOF_LONG_DOUBLE == 12
typedef long double uae_f96;
typedef uae_f96 fpu_register;
#elif SIZEOF_LONG_DOUBLE == 16
typedef long double uae_f128;
typedef uae_f128 fpu_register;
#else
#error "No float type bigger than 8 bytes, you lose."
#endif
/* We *do* use long doubles for the IEEE-based FPE */
#undef USE_LONG_DOUBLE
#define USE_LONG_DOUBLE 1
/* We need all those floating-point types */
typedef fpu_register fpu_extended;
typedef uae_f64 fpu_double;
typedef uae_f32 fpu_single;
#endif
#endif /* FPU_TYPES_H */