mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-07-06 15:29:18 +00:00
* 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:
parent
d3bda319a8
commit
c327eee41b
249
BasiliskII/src/uae_cpu/fpu/core.h
Normal file
249
BasiliskII/src/uae_cpu/fpu/core.h
Normal 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 */
|
188
BasiliskII/src/uae_cpu/fpu/exceptions.cpp
Normal file
188
BasiliskII/src/uae_cpu/fpu/exceptions.cpp
Normal 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
|
149
BasiliskII/src/uae_cpu/fpu/exceptions.h
Normal file
149
BasiliskII/src/uae_cpu/fpu/exceptions.h
Normal 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 */
|
169
BasiliskII/src/uae_cpu/fpu/flags.cpp
Normal file
169
BasiliskII/src/uae_cpu/fpu/flags.cpp
Normal 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
|
223
BasiliskII/src/uae_cpu/fpu/flags.h
Normal file
223
BasiliskII/src/uae_cpu/fpu/flags.h
Normal 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 */
|
49
BasiliskII/src/uae_cpu/fpu/fpu.h
Normal file
49
BasiliskII/src/uae_cpu/fpu/fpu.h
Normal 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 */
|
2111
BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp
Normal file
2111
BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp
Normal file
File diff suppressed because it is too large
Load Diff
149
BasiliskII/src/uae_cpu/fpu/fpu_ieee.h
Normal file
149
BasiliskII/src/uae_cpu/fpu/fpu_ieee.h
Normal 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
212
BasiliskII/src/uae_cpu/fpu/fpu_uae.h
Normal file
212
BasiliskII/src/uae_cpu/fpu/fpu_uae.h
Normal 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
@ -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 */
|
||||
|
@ -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
|
||||
|
147
BasiliskII/src/uae_cpu/fpu/impl.h
Normal file
147
BasiliskII/src/uae_cpu/fpu/impl.h
Normal 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 */
|
100
BasiliskII/src/uae_cpu/fpu/mathlib.cpp
Normal file
100
BasiliskII/src/uae_cpu/fpu/mathlib.cpp
Normal 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
|
992
BasiliskII/src/uae_cpu/fpu/mathlib.h
Normal file
992
BasiliskII/src/uae_cpu/fpu/mathlib.h
Normal 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 */
|
64
BasiliskII/src/uae_cpu/fpu/rounding.cpp
Normal file
64
BasiliskII/src/uae_cpu/fpu/rounding.cpp
Normal 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
|
154
BasiliskII/src/uae_cpu/fpu/rounding.h
Normal file
154
BasiliskII/src/uae_cpu/fpu/rounding.h
Normal 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 */
|
148
BasiliskII/src/uae_cpu/fpu/types.h
Normal file
148
BasiliskII/src/uae_cpu/fpu/types.h
Normal 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 */
|
Loading…
Reference in New Issue
Block a user