diff --git a/BasiliskII/src/uae_cpu/fpu/core.h b/BasiliskII/src/uae_cpu/fpu/core.h new file mode 100644 index 00000000..abadbfa7 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/core.h @@ -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 */ diff --git a/BasiliskII/src/uae_cpu/fpu/exceptions.cpp b/BasiliskII/src/uae_cpu/fpu/exceptions.cpp new file mode 100644 index 00000000..899295aa --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/exceptions.cpp @@ -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 diff --git a/BasiliskII/src/uae_cpu/fpu/exceptions.h b/BasiliskII/src/uae_cpu/fpu/exceptions.h new file mode 100644 index 00000000..028b876e --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/exceptions.h @@ -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 */ diff --git a/BasiliskII/src/uae_cpu/fpu/flags.cpp b/BasiliskII/src/uae_cpu/fpu/flags.cpp new file mode 100644 index 00000000..8f7f7c27 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/flags.cpp @@ -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 diff --git a/BasiliskII/src/uae_cpu/fpu/flags.h b/BasiliskII/src/uae_cpu/fpu/flags.h new file mode 100644 index 00000000..a7b6db4a --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/flags.h @@ -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 */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu.h b/BasiliskII/src/uae_cpu/fpu/fpu.h new file mode 100644 index 00000000..b20d48da --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/fpu.h @@ -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 */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp new file mode 100644 index 00000000..a5fdf9d6 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp @@ -0,0 +1,2111 @@ +/* + * UAE - The Un*x Amiga Emulator + * + * MC68881/MC68040 emulation + * + * Copyright 1996 Herman ten Brugge + * + * + * Following fixes by Lauri Pesonen, July 1999: + * + * FMOVEM list handling: + * The lookup tables did not work correctly, rewritten. + * FINT: + * (int) cast does not work, fixed. + * Further, now honors the FPU fpcr rounding modes. + * FINTRZ: + * (int) cast cannot be used, fixed. + * FGETEXP: + * Input argument value 0 returned erroneous value. + * FMOD: + * (int) cast cannot be used. Replaced by proper rounding. + * Quotient byte handling was missing. + * FREM: + * (int) cast cannot be used. Replaced by proper rounding. + * Quotient byte handling was missing. + * FSCALE: + * Input argument value 0 was not handled correctly. + * FMOVEM Control Registers to/from address FPU registers An: + * A bug caused the code never been called. + * FMOVEM Control Registers pre-decrement: + * Moving of control regs from memory to FPP was not handled properly, + * if not all of the three FPU registers were moved. + * Condition code "Not Greater Than or Equal": + * Returned erroneous value. + * FSINCOS: + * Cosine must be loaded first if same register. + * FMOVECR: + * Status register was not updated (yes, this affects it). + * FMOVE -> reg: + * Status register was not updated (yes, this affects it). + * FMOVE reg -> reg: + * Status register was not updated. + * FDBcc: + * The loop termination condition was wrong. + * Possible leak from int16 to int32 fixed. + * get_fp_value: + * Immediate addressing mode && Operation Length == Byte -> + * Use the low-order byte of the extension word. + * Now FPU fpcr high 16 bits are always read as zeroes, no matter what was + * written to them. + * + * Other: + * - Optimized single/double/extended to/from conversion functions. + * Huge speed boost, but not (necessarily) portable to other systems. + * Enabled/disabled by #define FPU_HAVE_IEEE_DOUBLE 1 + * - Optimized versions of FSCALE, FGETEXP, FGETMAN + * - Conversion routines now handle NaN and infinity better. + * - Some constants precalculated. Not all compilers can optimize the + * expressions previously used. + * + * TODO: + * - Floating point exceptions. + * - More Infinity/NaN/overflow/underflow checking. + * - FPU instruction_address (only needed when exceptions are implemented) + * - Should be written in assembly to support long doubles. + * - Precision rounding single/double + */ + +#include "sysdeps.h" +#include +#include "memory.h" +#include "readcpu.h" +#include "newcpu.h" +#include "main.h" +#define FPU_IMPLEMENTATION +#include "fpu/fpu.h" +#include "fpu/fpu_ieee.h" + +/* Global FPU context */ +fpu_t fpu; + +/* -------------------------------------------------------------------------- */ +/* --- Endianness --- */ +/* -------------------------------------------------------------------------- */ + +// Taken from glibc 2.1.x: endian.h +#define UAE_LITTLE_ENDIAN 1234 +#define UAE_BIG_ENDIAN 4321 + +#if WORDS_BIGENDIAN +#define UAE_BYTE_ORDER UAE_BIG_ENDIAN +#else +#define UAE_BYTE_ORDER UAE_LITTLE_ENDIAN +#endif + +// Some machines may need to use a different endianness for floating point values +// e.g. ARM in which case it is big endian +#define UAE_FLOAT_WORD_ORDER UAE_BYTE_ORDER + +/* -------------------------------------------------------------------------- */ +/* --- Scopes Definition --- */ +/* -------------------------------------------------------------------------- */ + +#undef PUBLIC +#define PUBLIC /**/ + +#undef PRIVATE +#define PRIVATE static + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + +/* -------------------------------------------------------------------------- */ +/* --- Native Support --- */ +/* -------------------------------------------------------------------------- */ + +#include "fpu/mathlib.h" +#include "fpu/flags.h" +#include "fpu/exceptions.h" +#include "fpu/rounding.h" +#include "fpu/impl.h" + +#include "fpu/mathlib.cpp" +#include "fpu/flags.cpp" +#include "fpu/exceptions.cpp" +#include "fpu/rounding.cpp" + +/* -------------------------------------------------------------------------- */ +/* --- Debugging --- */ +/* -------------------------------------------------------------------------- */ + +PUBLIC void FFPU fpu_dump_registers(void) +{ + for (int i = 0; i < 8; i++){ + printf ("FP%d: %g ", i, fpu_get_register(i)); + if ((i & 3) == 3) + printf ("\n"); + } +} + +PUBLIC void FFPU fpu_dump_flags(void) +{ + printf ("N=%d Z=%d I=%d NAN=%d\n", + (get_fpsr() & FPSR_CCB_NEGATIVE) != 0, + (get_fpsr() & FPSR_CCB_ZERO)!= 0, + (get_fpsr() & FPSR_CCB_INFINITY) != 0, + (get_fpsr() & FPSR_CCB_NAN) != 0); +} + +PRIVATE void FFPU dump_registers(const char * str) +{ +#if FPU_DEBUG && FPU_DUMP_REGISTERS + char temp_str[512]; + + sprintf(temp_str, "%s: %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f\n", + str, + fpu_get_register(0), fpu_get_register(1), fpu_get_register(2), + fpu_get_register(3), fpu_get_register(4), fpu_get_register(5), + fpu_get_register(6), fpu_get_register(7) ); + + fpu_debug((temp_str)); +#endif +} + +PRIVATE void FFPU dump_first_bytes(uae_u8 * buffer, uae_s32 actual) +{ +#if FPU_DEBUG && FPU_DUMP_FIRST_BYTES + char temp_buf1[256], temp_buf2[10]; + int bytes = sizeof(temp_buf1)/3-1-3; + if (actual < bytes) + bytes = actual; + + temp_buf1[0] = 0; + for (int i = 0; i < bytes; i++) { + sprintf(temp_buf2, "%02x ", (uae_u32)buffer[i]); + strcat(temp_buf1, temp_buf2); + } + + strcat(temp_buf1, "\n"); + fpu_debug((temp_buf1)); +#endif +} + +// 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) +{ + uae_u32 lsb = (uae_u32)fp_fabs(quotient) & 0x7f; + FPU fpsr.quotient = sign | (lsb << 16); +} + +// to_single +PRIVATE inline fpu_register FFPU make_single(uae_u32 value) +{ +#if 1 + // Use a single, otherwise some checks for NaN, Inf, Zero would have to + // be performed + fpu_single result; + fp_declare_init_shape(srp, result, single); + srp->ieee.negative = (value >> 31) & 1; + srp->ieee.exponent = (value >> 23) & FP_SINGLE_EXP_MAX; + srp->ieee.mantissa = value & 0x007fffff; + fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); + return result; +#elif 0 /* Original code */ + if ((value & 0x7fffffff) == 0) + return (0.0); + + fpu_register result; + uae_u32 * p = (uae_u32 *)&result; + + uae_u32 sign = (value & 0x80000000); + uae_u32 exp = ((value & 0x7F800000) >> 23) + 1023 - 127; + + p[FLO] = value << 29; + p[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); + + fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); + + return(result); +#endif +} + +// from_single +PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) +{ +#if 1 + fpu_single input = (fpu_single) src; + fp_declare_init_shape(sip, input, single); + uae_u32 result = (sip->ieee.negative << 31) + | (sip->ieee.exponent << 23) + | sip->ieee.mantissa; + fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result)); + return result; +#elif 0 /* Original code */ + if (src == 0.0) + return 0; + + uae_u32 result; + uae_u32 *p = (uae_u32 *)&src; + + uae_u32 sign = (p[FHI] & 0x80000000); + uae_u32 exp = (p[FHI] & 0x7FF00000) >> 20; + + if(exp + 127 < 1023) { + exp = 0; + } else if(exp > 1023 + 127) { + exp = 255; + } else { + exp = exp + 127 - 1023; + } + + result = sign | (exp << 23) | ((p[FHI] & 0x000FFFFF) << 3) | (p[FLO] >> 29); + + fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result)); + + return (result); +#endif +} + +// to_exten +PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) +{ +#if 1 + // FIXME: USE_QUAD_DOUBLE + fpu_extended result; + fp_declare_init_shape(srp, result, extended); + srp->ieee.negative = (wrd1 >> 31) & 1; + srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp->ieee.mantissa0 = wrd2; + srp->ieee.mantissa1 = wrd3; + fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); + return result; +#elif 0 /* original code */ + if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) + return 0.0; + + fpu_register result; + uae_u32 *p = (uae_u32 *)&result; + + uae_u32 sign = wrd1 & 0x80000000; + uae_u32 exp = (wrd1 >> 16) & 0x7fff; + + // The explicit integer bit is not set, must normalize. + if((wrd2 & 0x80000000) == 0) { + fpu_debug(("make_extended denormalized mantissa (%X,%X,%X)\n",wrd1,wrd2,wrd3)); + if( wrd2 | wrd3 ) { + // mantissa, not fraction. + uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3; + while( exp > 0 && (man & UVAL64(0x8000000000000000)) == 0 ) { + man <<= 1; + exp--; + } + wrd2 = (uae_u32)( man >> 32 ); + wrd3 = (uae_u32)( man & 0xFFFFFFFF ); + } else { + if(exp == 0x7FFF) { + // Infinity. + } else { + // Zero + exp = 16383 - 1023; + } + } + } + + if(exp < 16383 - 1023) { + // should set underflow. + exp = 0; + } else if(exp > 16383 + 1023) { + // should set overflow. + exp = 2047; + } else { + exp = exp + 1023 - 16383; + } + + // drop the explicit integer bit. + p[FLO] = (wrd2 << 21) | (wrd3 >> 11); + p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); + + fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); + + return(result); +#endif +} + +/* + Would be so much easier with full size floats :( + ... this is so vague. +*/ +// make_extended_no_normalize +PRIVATE inline void FFPU make_extended_no_normalize( + uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result +) +{ +#if 1 + // FIXME: USE_QUAD_DOUBLE + fp_declare_init_shape(srp, result, extended); + srp->ieee.negative = (wrd1 & 0x80000000) != 0; + srp->ieee.exponent = (wrd1 >> 16) & 0x7fff; + srp->ieee.mantissa0 = wrd2; + srp->ieee.mantissa1 = wrd3; +#elif 0 /* original code */ + // Is it zero? + if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { + make_zero_positive(result); + return; + } + + // Is it NaN? + if( (wrd1 & 0x7FFF0000) == 0x7FFF0000 ) { + if( (wrd1 & 0x0000FFFF) || wrd2 || wrd3 ) { + make_nan(result); + return; + } + } + + uae_u32 sign = wrd1 & 0x80000000; + uae_u32 exp = (wrd1 >> 16) & 0x7fff; + + if(exp < 16383 - 1023) { + // should set underflow. + exp = 0; + } else if(exp > 16383 + 1023) { + // should set overflow. + exp = 2047; + } else { + exp = exp + 1023 - 16383; + } + + // drop the explicit integer bit. + uae_u32 *p = (uae_u32 *)&result; + p[FLO] = (wrd2 << 21) | (wrd3 >> 11); + p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); + + fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(float)(*(double *)p))); +#endif +} + +// from_exten +PRIVATE inline void FFPU extract_extended(fpu_register const & src, + uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3 +) +{ +#if 1 + // FIXME: USE_QUAD_DOUBLE and non little-endian specificities + uae_u32 *p = (uae_u32 *)&src; + *wrd3 = p[0]; + *wrd2 = p[1]; + *wrd1 = ( (uae_u32)*((uae_u16 *)&p[2]) ) << 16; + fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); +#elif 0 /* original code */ + if (src == 0.0) { + *wrd1 = *wrd2 = *wrd3 = 0; + return; + } + + uae_u32 *p = (uae_u32 *)&src; + + fpu_debug(("extract_extended (%X,%X)\n",p[FLO],p[FHI])); + + uae_u32 sign = p[FHI] & 0x80000000; + + uae_u32 exp = ((p[FHI] >> 20) & 0x7ff); + // Check for maximum + if(exp == 0x7FF) { + exp = 0x7FFF; + } else { + exp += 16383 - 1023; + } + + *wrd1 = sign | (exp << 16); + // always set the explicit integer bit. + *wrd2 = 0x80000000 | ((p[FHI] & 0x000FFFFF) << 11) | ((p[FLO] & 0xFFE00000) >> 21); + *wrd3 = p[FLO] << 11; + + fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); +#endif +} + +// to_double +PRIVATE inline fpu_register FFPU make_double(uae_u32 wrd1, uae_u32 wrd2) +{ + union { + fpu_double value; + uae_u32 parts[2]; + } dest; +#ifdef WORDS_BIGENDIAN + dest.parts[0] = wrd1; + dest.parts[1] = wrd2; +#else + dest.parts[0] = wrd2; + dest.parts[1] = wrd1; +#endif + fpu_debug(("make_double (%X,%X) = %.04f\n",wrd1,wrd2,dest.value)); + return (fpu_register)(dest.value); +} + +// from_double +PRIVATE inline void FFPU extract_double(fpu_register const & src, + uae_u32 * wrd1, uae_u32 * wrd2 +) +{ + union { + fpu_double value; + uae_u32 parts[2]; + } dest; + dest.value = (fpu_double)src; +#ifdef WORDS_BIGENDIAN + *wrd1 = dest.parts[0]; + *wrd2 = dest.parts[1]; +#else + *wrd2 = dest.parts[0]; + *wrd1 = dest.parts[1]; +#endif + fpu_debug(("extract_double (%.04f) = %X,%X\n",(double)src,*wrd1,*wrd2)); +} + +// to_pack +PRIVATE inline fpu_register FFPU make_packed(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) +{ + fpu_double d; + char *cp; + char str[100]; + + cp = str; + if (wrd1 & 0x80000000) + *cp++ = '-'; + *cp++ = (char)((wrd1 & 0xf) + '0'); + *cp++ = '.'; + *cp++ = (char)(((wrd2 >> 28) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 16) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 12) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 8) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 4) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 0) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 28) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 16) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 12) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 8) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 4) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 0) & 0xf) + '0'); + *cp++ = 'E'; + if (wrd1 & 0x40000000) + *cp++ = '-'; + *cp++ = (char)(((wrd1 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd1 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd1 >> 16) & 0xf) + '0'); + *cp = 0; + sscanf(str, "%le", &d); + + fpu_debug(("make_packed str = %s\n",str)); + + fpu_debug(("make_packed(%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)d)); + return d; +} + +// from_pack +PRIVATE inline void FFPU extract_packed(fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) +{ + int i; + int t; + char *cp; + char str[100]; + + sprintf(str, "%.16e", src); + + fpu_debug(("extract_packed(%.04f,%s)\n",(double)src,str)); + + cp = str; + *wrd1 = *wrd2 = *wrd3 = 0; + if (*cp == '-') { + cp++; + *wrd1 = 0x80000000; + } + if (*cp == '+') + cp++; + *wrd1 |= (*cp++ - '0'); + if (*cp == '.') + cp++; + for (i = 0; i < 8; i++) { + *wrd2 <<= 4; + if (*cp >= '0' && *cp <= '9') + *wrd2 |= *cp++ - '0'; + } + for (i = 0; i < 8; i++) { + *wrd3 <<= 4; + if (*cp >= '0' && *cp <= '9') + *wrd3 |= *cp++ - '0'; + } + if (*cp == 'e' || *cp == 'E') { + cp++; + if (*cp == '-') { + cp++; + *wrd1 |= 0x40000000; + } + if (*cp == '+') + cp++; + t = 0; + for (i = 0; i < 3; i++) { + if (*cp >= '0' && *cp <= '9') + t = (t << 4) | (*cp++ - '0'); + } + *wrd1 |= t << 16; + } + + fpu_debug(("extract_packed(%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); +} + +PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_register & src) +{ + uaecptr tmppc; + uae_u16 tmp; + int size; + int mode; + int reg; + uae_u32 ad = 0; + static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; + static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; + + // fpu_debug(("get_fp_value(%X,%X)\n",(int)opcode,(int)extra)); + // dump_first_bytes( regs.pc_p-4, 16 ); + + if ((extra & 0x4000) == 0) { + src = FPU registers[(extra >> 10) & 7]; + return 1; + } + mode = (opcode >> 3) & 7; + reg = opcode & 7; + size = (extra >> 10) & 7; + + fpu_debug(("get_fp_value mode=%d, reg=%d, size=%d\n",(int)mode,(int)reg,(int)size)); + + switch (mode) { + case 0: + switch (size) { + case 6: + src = (fpu_register) (uae_s8) m68k_dreg (regs, reg); + break; + case 4: + src = (fpu_register) (uae_s16) m68k_dreg (regs, reg); + break; + case 0: + src = (fpu_register) (uae_s32) m68k_dreg (regs, reg); + break; + case 1: + src = make_single(m68k_dreg (regs, reg)); + break; + default: + return 0; + } + return 1; + case 1: + return 0; + case 2: + ad = m68k_areg (regs, reg); + break; + case 3: + ad = m68k_areg (regs, reg); + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + break; + case 4: + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + ad = m68k_areg (regs, reg); + break; + case 5: + ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + break; + case 6: + ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch (reg) { + case 0: + ad = (uae_s32) (uae_s16) next_iword(); + break; + case 1: + ad = next_ilong(); + break; + case 2: + ad = m68k_getpc (); + ad += (uae_s32) (uae_s16) next_iword(); + fpu_debug(("get_fp_value next_iword()=%X\n",ad-m68k_getpc()-2)); + break; + case 3: + tmppc = m68k_getpc (); + tmp = (uae_u16)next_iword(); + ad = get_disp_ea_020 (tmppc, tmp); + break; + case 4: + ad = m68k_getpc (); + m68k_setpc (ad + sz2[size]); + // Immediate addressing mode && Operation Length == Byte -> + // Use the low-order byte of the extension word. + if(size == 6) ad++; + break; + default: + return 0; + } + } + + fpu_debug(("get_fp_value m68k_getpc()=%X\n",m68k_getpc())); + fpu_debug(("get_fp_value ad=%X\n",ad)); + fpu_debug(("get_fp_value get_long (ad)=%X\n",get_long (ad))); + dump_first_bytes( get_real_address(ad)-64, 64 ); + dump_first_bytes( get_real_address(ad), 64 ); + + switch (size) { + case 0: + src = (fpu_register) (uae_s32) get_long (ad); + break; + case 1: + src = make_single(get_long (ad)); + break; + case 2: { + uae_u32 wrd1, wrd2, wrd3; + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + src = make_extended(wrd1, wrd2, wrd3); + break; + } + case 3: { + uae_u32 wrd1, wrd2, wrd3; + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + src = make_packed(wrd1, wrd2, wrd3); + break; + } + case 4: + src = (fpu_register) (uae_s16) get_word(ad); + break; + case 5: { + uae_u32 wrd1, wrd2; + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + src = make_double(wrd1, wrd2); + break; + } + case 6: + src = (fpu_register) (uae_s8) get_byte(ad); + break; + default: + return 0; + } + + // fpu_debug(("get_fp_value result = %.04f\n",(float)src)); + return 1; +} + +/* Convert the FP value to integer according to the current m68k rounding mode */ +PRIVATE inline uae_s32 FFPU toint(fpu_register const & src) +{ + fpu_register result; + switch (get_fpcr() & 0x30) { + case FPCR_ROUND_ZERO: + result = fp_round_to_zero(src); + break; + case FPCR_ROUND_MINF: + result = fp_round_to_minus_infinity(src); + break; + case FPCR_ROUND_NEAR: + result = fp_round_to_nearest(src); + break; + case FPCR_ROUND_PINF: + result = fp_round_to_plus_infinity(src); + break; + default: + result = src; /* should never be reached */ + break; + } + return (uae_s32)result; +} + +PRIVATE inline int FFPU put_fp_value (uae_u32 opcode, uae_u16 extra, fpu_register const & value) +{ + uae_u16 tmp; + uaecptr tmppc; + int size; + int mode; + int reg; + uae_u32 ad; + static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; + static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; + + // fpu_debug(("put_fp_value(%.04f,%X,%X)\n",(float)value,(int)opcode,(int)extra)); + + if ((extra & 0x4000) == 0) { + int dest_reg = (extra >> 10) & 7; + FPU registers[dest_reg] = value; + make_fpsr(FPU registers[dest_reg]); + return 1; + } + mode = (opcode >> 3) & 7; + reg = opcode & 7; + size = (extra >> 10) & 7; + ad = 0xffffffff; + switch (mode) { + case 0: + switch (size) { + case 6: + m68k_dreg (regs, reg) = ((toint(value) & 0xff) + | (m68k_dreg (regs, reg) & ~0xff)); + break; + case 4: + m68k_dreg (regs, reg) = ((toint(value) & 0xffff) + | (m68k_dreg (regs, reg) & ~0xffff)); + break; + case 0: + m68k_dreg (regs, reg) = toint(value); + break; + case 1: + m68k_dreg (regs, reg) = extract_single(value); + break; + default: + return 0; + } + return 1; + case 1: + return 0; + case 2: + ad = m68k_areg (regs, reg); + break; + case 3: + ad = m68k_areg (regs, reg); + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + break; + case 4: + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + ad = m68k_areg (regs, reg); + break; + case 5: + ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + break; + case 6: + ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch (reg) { + case 0: + ad = (uae_s32) (uae_s16) next_iword(); + break; + case 1: + ad = next_ilong(); + break; + case 2: + ad = m68k_getpc (); + ad += (uae_s32) (uae_s16) next_iword(); + break; + case 3: + tmppc = m68k_getpc (); + tmp = (uae_u16)next_iword(); + ad = get_disp_ea_020 (tmppc, tmp); + break; + case 4: + ad = m68k_getpc (); + m68k_setpc (ad + sz2[size]); + break; + default: + return 0; + } + } + switch (size) { + case 0: + put_long (ad, toint(value)); + break; + case 1: + put_long (ad, extract_single(value)); + break; + case 2: { + uae_u32 wrd1, wrd2, wrd3; + extract_extended(value, &wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + break; + } + case 3: { + uae_u32 wrd1, wrd2, wrd3; + extract_packed(value, &wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + break; + } + case 4: + put_word(ad, (uae_s16) toint(value)); + break; + case 5: { + uae_u32 wrd1, wrd2; + extract_double(value, &wrd1, &wrd2); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + break; + } + case 6: + put_byte(ad, (uae_s8) toint(value)); + break; + default: + return 0; + } + return 1; +} + +PRIVATE inline int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) +{ + uae_u16 tmp; + uaecptr tmppc; + int mode; + int reg; + + mode = (opcode >> 3) & 7; + reg = opcode & 7; + switch (mode) { + case 0: + case 1: + return 0; + case 2: + *ad = m68k_areg (regs, reg); + break; + case 3: + *ad = m68k_areg (regs, reg); + break; + case 4: + *ad = m68k_areg (regs, reg); + break; + case 5: + *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + break; + case 6: + *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch (reg) { + case 0: + *ad = (uae_s32) (uae_s16) next_iword(); + break; + case 1: + *ad = next_ilong(); + break; + case 2: + *ad = m68k_getpc (); + *ad += (uae_s32) (uae_s16) next_iword(); + break; + case 3: + tmppc = m68k_getpc (); + tmp = (uae_u16)next_iword(); + *ad = get_disp_ea_020 (tmppc, tmp); + break; + default: + return 0; + } + } + return 1; +} + +#if FPU_DEBUG +# define CONDRET(s,x) fpu_debug(("fpp_cond %s = %d\n",s,(uint32)(x))); return (x) +#else +# define CONDRET(s,x) return (x) +#endif + +PRIVATE inline int FFPU fpp_cond(int condition) +{ + int N = (FPU result < 0.0); + int Z = (FPU result == 0.0); + int NaN = isnan(FPU result); + + if (NaN) + N = Z = 0; + + switch (condition) { + case 0x00: CONDRET("False",0); + case 0x01: CONDRET("Equal",Z); + case 0x02: CONDRET("Ordered Greater Than",!(NaN || Z || N)); + case 0x03: CONDRET("Ordered Greater Than or Equal",Z || !(NaN || N)); + case 0x04: CONDRET("Ordered Less Than",N && !(NaN || Z)); + case 0x05: CONDRET("Ordered Less Than or Equal",Z || (N && !NaN)); + case 0x06: CONDRET("Ordered Greater or Less Than",!(NaN || Z)); + case 0x07: CONDRET("Ordered",!NaN); + case 0x08: CONDRET("Unordered",NaN); + case 0x09: CONDRET("Unordered or Equal",NaN || Z); + case 0x0a: CONDRET("Unordered or Greater Than",NaN || !(N || Z)); + case 0x0b: CONDRET("Unordered or Greater or Equal",NaN || Z || !N); + case 0x0c: CONDRET("Unordered or Less Than",NaN || (N && !Z)); + case 0x0d: CONDRET("Unordered or Less or Equal",NaN || Z || N); + case 0x0e: CONDRET("Not Equal",!Z); + case 0x0f: CONDRET("True",1); + case 0x10: CONDRET("Signaling False",0); + case 0x11: CONDRET("Signaling Equal",Z); + case 0x12: CONDRET("Greater Than",!(NaN || Z || N)); + case 0x13: CONDRET("Greater Than or Equal",Z || !(NaN || N)); + case 0x14: CONDRET("Less Than",N && !(NaN || Z)); + case 0x15: CONDRET("Less Than or Equal",Z || (N && !NaN)); + case 0x16: CONDRET("Greater or Less Than",!(NaN || Z)); + case 0x17: CONDRET("Greater, Less or Equal",!NaN); + case 0x18: CONDRET("Not Greater, Less or Equal",NaN); + case 0x19: CONDRET("Not Greater or Less Than",NaN || Z); + case 0x1a: CONDRET("Not Less Than or Equal",NaN || !(N || Z)); + case 0x1b: CONDRET("Not Less Than",NaN || Z || !N); + case 0x1c: CONDRET("Not Greater Than or Equal", NaN || (N && !Z)); + case 0x1d: CONDRET("Not Greater Than",NaN || Z || N); + case 0x1e: CONDRET("Signaling Not Equal",!Z); + case 0x1f: CONDRET("Signaling True",1); + default: CONDRET("",-1); + } +} + +void FFPU fpuop_dbcc(uae_u32 opcode, uae_u32 extra) +{ + fpu_debug(("fdbcc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + + uaecptr pc = (uae_u32) m68k_getpc (); + uae_s32 disp = (uae_s32) (uae_s16) next_iword(); + int cc = fpp_cond(extra & 0x3f); + if (cc == -1) { + m68k_setpc (pc - 4); + op_illg (opcode); + } else if (!cc) { + int reg = opcode & 0x7; + + // this may have leaked. + /* + m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & ~0xffff) + | ((m68k_dreg (regs, reg) - 1) & 0xffff)); + */ + m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & 0xffff0000) + | (((m68k_dreg (regs, reg) & 0xffff) - 1) & 0xffff)); + + + // condition reversed. + // if ((m68k_dreg (regs, reg) & 0xffff) == 0xffff) + if ((m68k_dreg (regs, reg) & 0xffff) != 0xffff) + m68k_setpc (pc + disp); + } +} + +void FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) +{ + fpu_debug(("fscc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + + uae_u32 ad; + int cc = fpp_cond(extra & 0x3f); + if (cc == -1) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + } + else if ((opcode & 0x38) == 0) { + m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) | + (cc ? 0xff : 0x00); + } + else if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + } + else + put_byte(ad, cc ? 0xff : 0x00); +} + +void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) +{ + fpu_debug(("ftrapcc_opp %X at %08lx\n", (uae_u32)opcode, m68k_getpc ())); + + int cc = fpp_cond(opcode & 0x3f); + if (cc == -1) { + m68k_setpc (oldpc); + op_illg (opcode); + } + if (cc) + Exception(7, oldpc - 2); +} + +// NOTE that we get here also when there is a FNOP (nontrapping false, displ 0) +void FFPU fpuop_bcc(uae_u32 opcode, uaecptr pc, uae_u32 extra) +{ + fpu_debug(("fbcc_opp %X, %X at %08lx, jumpto=%X\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc (), extra )); + + int cc = fpp_cond(opcode & 0x3f); + if (cc == -1) { + m68k_setpc (pc); + op_illg (opcode); + } + else if (cc) { + if ((opcode & 0x40) == 0) + extra = (uae_s32) (uae_s16) extra; + m68k_setpc (pc + extra); + } +} + +// FSAVE has no post-increment +// 0x1f180000 == IDLE state frame, coprocessor version number 1F +void FFPU fpuop_save(uae_u32 opcode) +{ + fpu_debug(("fsave_opp at %08lx\n", m68k_getpc ())); + + uae_u32 ad; + int incr = (opcode & 0x38) == 0x20 ? -1 : 1; + int i; + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 2); + op_illg (opcode); + return; + } + + if (CPUType == 4) { + // Put 4 byte 68040 IDLE frame. + if (incr < 0) { + ad -= 4; + put_long (ad, 0x41000000); + } + else { + put_long (ad, 0x41000000); + ad += 4; + } + } else { + // Put 28 byte 68881 IDLE frame. + if (incr < 0) { + fpu_debug(("fsave_opp pre-decrement\n")); + ad -= 4; + // What's this? Some BIU flags, or (incorrectly placed) command/condition? + put_long (ad, 0x70000000); + for (i = 0; i < 5; i++) { + ad -= 4; + put_long (ad, 0x00000000); + } + ad -= 4; + put_long (ad, 0x1f180000); // IDLE, vers 1f + } + else { + put_long (ad, 0x1f180000); // IDLE, vers 1f + ad += 4; + for (i = 0; i < 5; i++) { + put_long (ad, 0x00000000); + ad += 4; + } + // What's this? Some BIU flags, or (incorrectly placed) command/condition? + put_long (ad, 0x70000000); + ad += 4; + } + } + if ((opcode & 0x38) == 0x18) { + m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 + fpu_debug(("PROBLEM: fsave_opp post-increment\n")); + } + if ((opcode & 0x38) == 0x20) { + m68k_areg (regs, opcode & 7) = ad; + fpu_debug(("fsave_opp pre-decrement %X -> A%d\n",ad,opcode & 7)); + } +} + +// FRESTORE has no pre-decrement +void FFPU fpuop_restore(uae_u32 opcode) +{ + fpu_debug(("frestore_opp at %08lx\n", m68k_getpc ())); + + uae_u32 ad; + uae_u32 d; + int incr = (opcode & 0x38) == 0x20 ? -1 : 1; + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 2); + op_illg (opcode); + return; + } + + if (CPUType == 4) { + // 68040 + if (incr < 0) { + fpu_debug(("PROBLEM: frestore_opp incr < 0\n")); + // this may be wrong, but it's never called. + ad -= 4; + d = get_long (ad); + if ((d & 0xff000000) != 0) { // Not a NULL frame? + if ((d & 0x00ff0000) == 0) { // IDLE + fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); + } + else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP + fpu_debug(("PROBLEM: frestore_opp found UNIMP frame at %X\n",ad-4)); + ad -= 44; + } + else if ((d & 0x00ff0000) == 0x00600000) { // BUSY + fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); + ad -= 92; + } + } + } + else { + d = get_long (ad); + fpu_debug(("frestore_opp frame at %X = %X\n",ad,d)); + ad += 4; + if ((d & 0xff000000) != 0) { // Not a NULL frame? + if ((d & 0x00ff0000) == 0) { // IDLE + fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); + } + else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP + fpu_debug(("PROBLEM: frestore_opp found UNIMP frame at %X\n",ad-4)); + ad += 44; + } + else if ((d & 0x00ff0000) == 0x00600000) { // BUSY + fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); + ad += 92; + } + } + } + } + else { + // 68881 + if (incr < 0) { + fpu_debug(("PROBLEM: frestore_opp incr < 0\n")); + // this may be wrong, but it's never called. + ad -= 4; + d = get_long (ad); + if ((d & 0xff000000) != 0) { + if ((d & 0x00ff0000) == 0x00180000) + ad -= 6 * 4; + else if ((d & 0x00ff0000) == 0x00380000) + ad -= 14 * 4; + else if ((d & 0x00ff0000) == 0x00b40000) + ad -= 45 * 4; + } + } + else { + d = get_long (ad); + fpu_debug(("frestore_opp frame at %X = %X\n",ad,d)); + ad += 4; + if ((d & 0xff000000) != 0) { // Not a NULL frame? + if ((d & 0x00ff0000) == 0x00180000) { // IDLE + fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); + ad += 6 * 4; + } + else if ((d & 0x00ff0000) == 0x00380000) {// UNIMP? shouldn't it be 3C? + ad += 14 * 4; + fpu_debug(("PROBLEM: frestore_opp found UNIMP? frame at %X\n",ad-4)); + } + else if ((d & 0x00ff0000) == 0x00b40000) {// BUSY + fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); + ad += 45 * 4; + } + } + } + } + if ((opcode & 0x38) == 0x18) { + m68k_areg (regs, opcode & 7) = ad; + fpu_debug(("frestore_opp post-increment %X -> A%d\n",ad,opcode & 7)); + } + if ((opcode & 0x38) == 0x20) { + m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 + fpu_debug(("PROBLEM: frestore_opp pre-decrement\n")); + } +} + +void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) +{ + int reg; + fpu_register src; + + fpu_debug(("FPP %04lx %04x at %08lx\n", opcode & 0xffff, extra & 0xffff, + m68k_getpc () - 4)); + + dump_registers( "START"); + + switch ((extra >> 13) & 0x7) { + case 3: + fpu_debug(("FMOVE -> \n")); + if (put_fp_value (opcode, extra, FPU registers[(extra >> 7) & 7]) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + } + dump_registers( "END "); + return; + case 4: + case 5: + if ((opcode & 0x38) == 0) { + if (extra & 0x2000) { // dr bit + if (extra & 0x1000) { + // according to the manual, the msb bits are always zero. + m68k_dreg (regs, opcode & 7) = get_fpcr() & 0xFFFF; + fpu_debug(("FMOVEM FPU fpcr (%X) -> D%d\n", get_fpcr(), opcode & 7)); + } + if (extra & 0x0800) { + m68k_dreg (regs, opcode & 7) = get_fpsr(); + fpu_debug(("FMOVEM FPU fpsr (%X) -> D%d\n", get_fpsr(), opcode & 7)); + } + if (extra & 0x0400) { + m68k_dreg (regs, opcode & 7) = FPU instruction_address; + fpu_debug(("FMOVEM FPU instruction_address (%X) -> D%d\n", FPU instruction_address, opcode & 7)); + } + } + else { + if (extra & 0x1000) { + set_fpcr( m68k_dreg (regs, opcode & 7) ); + fpu_debug(("FMOVEM D%d (%X) -> FPU fpcr\n", opcode & 7, get_fpcr())); + } + if (extra & 0x0800) { + set_fpsr( m68k_dreg (regs, opcode & 7) ); + fpu_debug(("FMOVEM D%d (%X) -> FPU fpsr\n", opcode & 7, get_fpsr())); + } + if (extra & 0x0400) { + FPU instruction_address = m68k_dreg (regs, opcode & 7); + fpu_debug(("FMOVEM D%d (%X) -> FPU instruction_address\n", opcode & 7, FPU instruction_address)); + } + } +// } else if ((opcode & 0x38) == 1) { + } + else if ((opcode & 0x38) == 8) { + if (extra & 0x2000) { // dr bit + if (extra & 0x1000) { + // according to the manual, the msb bits are always zero. + m68k_areg (regs, opcode & 7) = get_fpcr() & 0xFFFF; + fpu_debug(("FMOVEM FPU fpcr (%X) -> A%d\n", get_fpcr(), opcode & 7)); + } + if (extra & 0x0800) { + m68k_areg (regs, opcode & 7) = get_fpsr(); + fpu_debug(("FMOVEM FPU fpsr (%X) -> A%d\n", get_fpsr(), opcode & 7)); + } + if (extra & 0x0400) { + m68k_areg (regs, opcode & 7) = FPU instruction_address; + fpu_debug(("FMOVEM FPU instruction_address (%X) -> A%d\n", FPU instruction_address, opcode & 7)); + } + } else { + if (extra & 0x1000) { + set_fpcr( m68k_areg (regs, opcode & 7) ); + fpu_debug(("FMOVEM A%d (%X) -> FPU fpcr\n", opcode & 7, get_fpcr())); + } + if (extra & 0x0800) { + set_fpsr( m68k_areg (regs, opcode & 7) ); + fpu_debug(("FMOVEM A%d (%X) -> FPU fpsr\n", opcode & 7, get_fpsr())); + } + if (extra & 0x0400) { + FPU instruction_address = m68k_areg (regs, opcode & 7); + fpu_debug(("FMOVEM A%d (%X) -> FPU instruction_address\n", opcode & 7, FPU instruction_address)); + } + } + } + else if ((opcode & 0x3f) == 0x3c) { + if ((extra & 0x2000) == 0) { + if (extra & 0x1000) { + set_fpcr( next_ilong() ); + fpu_debug(("FMOVEM #<%X> -> FPU fpcr\n", get_fpcr())); + } + if (extra & 0x0800) { + set_fpsr( next_ilong() ); + fpu_debug(("FMOVEM #<%X> -> FPU fpsr\n", get_fpsr())); + } + if (extra & 0x0400) { + FPU instruction_address = next_ilong(); + fpu_debug(("FMOVEM #<%X> -> FPU instruction_address\n", FPU instruction_address)); + } + } + } + else if (extra & 0x2000) { + /* FMOVEM FPP->memory */ + uae_u32 ad; + int incr = 0; + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + if ((opcode & 0x38) == 0x20) { + if (extra & 0x1000) + incr += 4; + if (extra & 0x0800) + incr += 4; + if (extra & 0x0400) + incr += 4; + } + ad -= incr; + if (extra & 0x1000) { + // according to the manual, the msb bits are always zero. + put_long (ad, get_fpcr() & 0xFFFF); + fpu_debug(("FMOVEM FPU fpcr (%X) -> mem %X\n", get_fpcr(), ad )); + ad += 4; + } + if (extra & 0x0800) { + put_long (ad, get_fpsr()); + fpu_debug(("FMOVEM FPU fpsr (%X) -> mem %X\n", get_fpsr(), ad )); + ad += 4; + } + if (extra & 0x0400) { + put_long (ad, FPU instruction_address); + fpu_debug(("FMOVEM FPU instruction_address (%X) -> mem %X\n", FPU instruction_address, ad )); + ad += 4; + } + ad -= incr; + if ((opcode & 0x38) == 0x18) // post-increment? + m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) // pre-decrement? + m68k_areg (regs, opcode & 7) = ad; + } + else { + /* FMOVEM memory->FPP */ + uae_u32 ad; + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + + // ad = (opcode & 0x38) == 0x20 ? ad - 12 : ad; + int incr = 0; + if((opcode & 0x38) == 0x20) { + if (extra & 0x1000) + incr += 4; + if (extra & 0x0800) + incr += 4; + if (extra & 0x0400) + incr += 4; + ad = ad - incr; + } + + if (extra & 0x1000) { + set_fpcr( get_long (ad) ); + fpu_debug(("FMOVEM mem %X (%X) -> FPU fpcr\n", ad, get_fpcr() )); + ad += 4; + } + if (extra & 0x0800) { + set_fpsr( get_long (ad) ); + fpu_debug(("FMOVEM mem %X (%X) -> FPU fpsr\n", ad, get_fpsr() )); + ad += 4; + } + if (extra & 0x0400) { + FPU instruction_address = get_long (ad); + fpu_debug(("FMOVEM mem %X (%X) -> FPU instruction_address\n", ad, FPU instruction_address )); + ad += 4; + } + if ((opcode & 0x38) == 0x18) // post-increment? + m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) // pre-decrement? +// m68k_areg (regs, opcode & 7) = ad - 12; + m68k_areg (regs, opcode & 7) = ad - incr; + } + dump_registers( "END "); + return; + case 6: + case 7: { + uae_u32 ad, list = 0; + int incr = 0; + if (extra & 0x2000) { + /* FMOVEM FPP->memory */ + fpu_debug(("FMOVEM FPP->memory\n")); + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + switch ((extra >> 11) & 3) { + case 0: /* static pred */ + list = extra & 0xff; + incr = -1; + break; + case 1: /* dynamic pred */ + list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + incr = -1; + break; + case 2: /* static postinc */ + list = extra & 0xff; + incr = 1; + break; + case 3: /* dynamic postinc */ + list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + incr = 1; + break; + } + + if (incr < 0) { + for(reg=7; reg>=0; reg--) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + extract_extended(FPU registers[reg],&wrd1, &wrd2, &wrd3); + ad -= 4; + put_long (ad, wrd3); + ad -= 4; + put_long (ad, wrd2); + ad -= 4; + put_long (ad, wrd1); + } + list <<= 1; + } + } + else { + for(reg=0; reg<8; reg++) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + extract_extended(FPU registers[reg],&wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + ad += 4; + } + list <<= 1; + } + } + if ((opcode & 0x38) == 0x18) // post-increment? + m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) // pre-decrement? + m68k_areg (regs, opcode & 7) = ad; + } + else { + /* FMOVEM memory->FPP */ + fpu_debug(("FMOVEM memory->FPP\n")); + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + switch ((extra >> 11) & 3) { + case 0: /* static pred */ + fpu_debug(("memory->FMOVEM FPP not legal mode.\n")); + list = extra & 0xff; + incr = -1; + break; + case 1: /* dynamic pred */ + fpu_debug(("memory->FMOVEM FPP not legal mode.\n")); + list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + incr = -1; + break; + case 2: /* static postinc */ + list = extra & 0xff; + incr = 1; + break; + case 3: /* dynamic postinc */ + list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + incr = 1; + break; + } + + /**/ + if (incr < 0) { + // not reached + for(reg=7; reg>=0; reg--) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + ad -= 4; + wrd3 = get_long (ad); + ad -= 4; + wrd2 = get_long (ad); + ad -= 4; + wrd1 = get_long (ad); + // FPU registers[reg] = make_extended(wrd1, wrd2, wrd3); + make_extended_no_normalize (wrd1, wrd2, wrd3, FPU registers[reg]); + } + list <<= 1; + } + } + else { + for(reg=0; reg<8; reg++) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + ad += 4; + // FPU registers[reg] = make_extended(wrd1, wrd2, wrd3); + make_extended_no_normalize (wrd1, wrd2, wrd3, FPU registers[reg]); + } + list <<= 1; + } + } + if ((opcode & 0x38) == 0x18) // post-increment? + m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) // pre-decrement? + m68k_areg (regs, opcode & 7) = ad; + } + dump_registers( "END "); + return; + } + case 0: + case 2: + reg = (extra >> 7) & 7; + if ((extra & 0xfc00) == 0x5c00) { + fpu_debug(("FMOVECR memory->FPP\n")); + switch (extra & 0x7f) { + case 0x00: + // FPU registers[reg] = 4.0 * atan(1.0); + FPU registers[reg] = 3.1415926535897932384626433832795; + fpu_debug(("FP const: Pi\n")); + break; + case 0x0b: + // FPU registers[reg] = log10 (2.0); + FPU registers[reg] = 0.30102999566398119521373889472449; + fpu_debug(("FP const: Log 10 (2)\n")); + break; + case 0x0c: + // FPU registers[reg] = exp (1.0); + FPU registers[reg] = 2.7182818284590452353602874713527; + fpu_debug(("FP const: e\n")); + break; + case 0x0d: + // FPU registers[reg] = log (exp (1.0)) / log (2.0); + FPU registers[reg] = 1.4426950408889634073599246810019; + fpu_debug(("FP const: Log 2 (e)\n")); + break; + case 0x0e: + // FPU registers[reg] = log (exp (1.0)) / log (10.0); + FPU registers[reg] = 0.43429448190325182765112891891661; + fpu_debug(("FP const: Log 10 (e)\n")); + break; + case 0x0f: + FPU registers[reg] = 0.0; + fpu_debug(("FP const: zero\n")); + break; + case 0x30: + // FPU registers[reg] = log (2.0); + FPU registers[reg] = 0.69314718055994530941723212145818; + fpu_debug(("FP const: ln(2)\n")); + break; + case 0x31: + // FPU registers[reg] = log (10.0); + FPU registers[reg] = 2.3025850929940456840179914546844; + fpu_debug(("FP const: ln(10)\n")); + break; + case 0x32: + // ?? + FPU registers[reg] = 1.0e0; + fpu_debug(("FP const: 1.0e0\n")); + break; + case 0x33: + FPU registers[reg] = 1.0e1; + fpu_debug(("FP const: 1.0e1\n")); + break; + case 0x34: + FPU registers[reg] = 1.0e2; + fpu_debug(("FP const: 1.0e2\n")); + break; + case 0x35: + FPU registers[reg] = 1.0e4; + fpu_debug(("FP const: 1.0e4\n")); + break; + case 0x36: + FPU registers[reg] = 1.0e8; + fpu_debug(("FP const: 1.0e8\n")); + break; + case 0x37: + FPU registers[reg] = 1.0e16; + fpu_debug(("FP const: 1.0e16\n")); + break; + case 0x38: + FPU registers[reg] = 1.0e32; + fpu_debug(("FP const: 1.0e32\n")); + break; + case 0x39: + FPU registers[reg] = 1.0e64; + fpu_debug(("FP const: 1.0e64\n")); + break; + case 0x3a: + FPU registers[reg] = 1.0e128; + fpu_debug(("FP const: 1.0e128\n")); + break; + case 0x3b: + FPU registers[reg] = 1.0e256; + fpu_debug(("FP const: 1.0e256\n")); + break; + case 0x3c: + FPU registers[reg] = 1.0e512; + fpu_debug(("FP const: 1.0e512\n")); + break; + case 0x3d: + FPU registers[reg] = 1.0e1024; + fpu_debug(("FP const: 1.0e1024\n")); + break; + case 0x3e: + FPU registers[reg] = 1.0e2048; + fpu_debug(("FP const: 1.0e2048\n")); + break; + case 0x3f: + FPU registers[reg] = 1.0e4096; + fpu_debug(("FP const: 1.0e4096\n")); + break; + default: + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + break; + } + // these *do* affect the status reg + make_fpsr(FPU registers[reg]); + dump_registers( "END "); + return; + } + + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + fpu_debug(("returned from get_fp_value m68k_getpc()=%X\n",m68k_getpc())); + + if (FPU is_integral) { + // 68040-specific operations + switch (extra & 0x7f) { + case 0x40: /* FSMOVE */ + fpu_debug(("FSMOVE %.04f\n",(double)src)); + FPU registers[reg] = (float)src; + make_fpsr(FPU registers[reg]); + break; + case 0x44: /* FDMOVE */ + fpu_debug(("FDMOVE %.04f\n",(double)src)); + FPU registers[reg] = (double)src; + make_fpsr(FPU registers[reg]); + break; + case 0x41: /* FSSQRT */ + fpu_debug(("FSQRT %.04f\n",(double)src)); + FPU registers[reg] = (float)fp_sqrt (src); + make_fpsr(FPU registers[reg]); + break; + case 0x45: /* FDSQRT */ + fpu_debug(("FSQRT %.04f\n",(double)src)); + FPU registers[reg] = (double)fp_sqrt (src); + make_fpsr(FPU registers[reg]); + break; + case 0x58: /* FSABS */ + fpu_debug(("FSABS %.04f\n",(double)src)); + FPU registers[reg] = (float)fp_fabs(src); + make_fpsr(FPU registers[reg]); + break; + case 0x5c: /* FDABS */ + fpu_debug(("FDABS %.04f\n",(double)src)); + FPU registers[reg] = (double)fp_fabs(src); + make_fpsr(FPU registers[reg]); + break; + case 0x5a: /* FSNEG */ + fpu_debug(("FSNEG %.04f\n",(double)src)); + FPU registers[reg] = (float)-src; + make_fpsr(FPU registers[reg]); + break; + case 0x5e: /* FDNEG */ + fpu_debug(("FDNEG %.04f\n",(double)src)); + FPU registers[reg] = (double)-src; + make_fpsr(FPU registers[reg]); + break; + case 0x60: /* FSDIV */ + fpu_debug(("FSDIV %.04f\n",(double)src)); + FPU registers[reg] = (float)(FPU registers[reg] / src); + make_fpsr(FPU registers[reg]); + break; + case 0x64: /* FDDIV */ + fpu_debug(("FDDIV %.04f\n",(double)src)); + FPU registers[reg] = (double)(FPU registers[reg] / src); + make_fpsr(FPU registers[reg]); + break; + case 0x62: /* FSADD */ + fpu_debug(("FSADD %.04f\n",(double)src)); + FPU registers[reg] = (float)(FPU registers[reg] + src); + make_fpsr(FPU registers[reg]); + break; + case 0x66: /* FDADD */ + fpu_debug(("FDADD %.04f\n",(double)src)); + FPU registers[reg] = (double)(FPU registers[reg] + src); + make_fpsr(FPU registers[reg]); + break; + case 0x68: /* FSSUB */ + fpu_debug(("FSSUB %.04f\n",(double)src)); + FPU registers[reg] = (float)(FPU registers[reg] - src); + make_fpsr(FPU registers[reg]); + break; + case 0x6c: /* FDSUB */ + fpu_debug(("FDSUB %.04f\n",(double)src)); + FPU registers[reg] = (double)(FPU registers[reg] - src); + make_fpsr(FPU registers[reg]); + break; + case 0x63: /* FSMUL */ + case 0x67: /* FDMUL */ + fpu_debug(("FMUL %.04f\n",(double)src)); + get_dest_flags(FPU registers[reg]); + get_source_flags(src); + if(fl_dest.in_range && fl_source.in_range) { + if ((extra & 0x7f) == 0x63) + FPU registers[reg] = (float)(FPU registers[reg] * src); + else + FPU registers[reg] = (double)(FPU registers[reg] * src); + } + else if (fl_dest.nan || fl_source.nan || + fl_dest.zero && fl_source.infinity || + fl_dest.infinity && fl_source.zero ) { + make_nan( FPU registers[reg] ); + } + else if (fl_dest.zero || fl_source.zero ) { + if (fl_dest.negative && !fl_source.negative || + !fl_dest.negative && fl_source.negative) { + make_zero_negative(FPU registers[reg]); + } + else { + make_zero_positive(FPU registers[reg]); + } + } + else { + if( fl_dest.negative && !fl_source.negative || + !fl_dest.negative && fl_source.negative) { + make_inf_negative(FPU registers[reg]); + } + else { + make_inf_positive(FPU registers[reg]); + } + } + make_fpsr(FPU registers[reg]); + break; + default: + // Continue decode-execute 6888x instructions below + goto process_6888x_instructions; + } + fpu_debug(("END m68k_getpc()=%X\n",m68k_getpc())); + dump_registers( "END "); + return; + } + + process_6888x_instructions: + switch (extra & 0x7f) { + case 0x00: /* FMOVE */ + fpu_debug(("FMOVE %.04f\n",(double)src)); + FPU registers[reg] = src; + make_fpsr(FPU registers[reg]); + break; + case 0x01: /* FINT */ + fpu_debug(("FINT %.04f\n",(double)src)); + FPU registers[reg] = toint(src); + make_fpsr(FPU registers[reg]); + break; + case 0x02: /* FSINH */ + fpu_debug(("FSINH %.04f\n",(double)src)); + FPU registers[reg] = fp_sinh (src); + make_fpsr(FPU registers[reg]); + break; + case 0x03: /* FINTRZ */ + fpu_debug(("FINTRZ %.04f\n",(double)src)); + FPU registers[reg] = fp_round_to_zero(src); + make_fpsr(FPU registers[reg]); + break; + case 0x04: /* FSQRT */ + fpu_debug(("FSQRT %.04f\n",(double)src)); + FPU registers[reg] = fp_sqrt (src); + make_fpsr(FPU registers[reg]); + break; + case 0x06: /* FLOGNP1 */ + fpu_debug(("FLOGNP1 %.04f\n",(double)src)); + FPU registers[reg] = fp_log (src + 1.0); + make_fpsr(FPU registers[reg]); + break; + case 0x08: /* FETOXM1 */ + fpu_debug(("FETOXM1 %.04f\n",(double)src)); + FPU registers[reg] = fp_exp (src) - 1.0; + make_fpsr(FPU registers[reg]); + break; + case 0x09: /* FTANH */ + fpu_debug(("FTANH %.04f\n",(double)src)); + FPU registers[reg] = fp_tanh (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0a: /* FATAN */ + fpu_debug(("FATAN %.04f\n",(double)src)); + FPU registers[reg] = fp_atan (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0c: /* FASIN */ + fpu_debug(("FASIN %.04f\n",(double)src)); + FPU registers[reg] = fp_asin (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0d: /* FATANH */ + fpu_debug(("FATANH %.04f\n",(double)src)); + FPU registers[reg] = fp_atanh (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0e: /* FSIN */ + fpu_debug(("FSIN %.04f\n",(double)src)); + FPU registers[reg] = fp_sin (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0f: /* FTAN */ + fpu_debug(("FTAN %.04f\n",(double)src)); + FPU registers[reg] = fp_tan (src); + make_fpsr(FPU registers[reg]); + break; + case 0x10: /* FETOX */ + fpu_debug(("FETOX %.04f\n",(double)src)); + FPU registers[reg] = fp_exp (src); + make_fpsr(FPU registers[reg]); + break; + case 0x11: /* FTWOTOX */ + fpu_debug(("FTWOTOX %.04f\n",(double)src)); + FPU registers[reg] = fp_pow(2.0, src); + make_fpsr(FPU registers[reg]); + break; + case 0x12: /* FTENTOX */ + fpu_debug(("FTENTOX %.04f\n",(double)src)); + FPU registers[reg] = fp_pow(10.0, src); + make_fpsr(FPU registers[reg]); + break; + case 0x14: /* FLOGN */ + fpu_debug(("FLOGN %.04f\n",(double)src)); + FPU registers[reg] = fp_log (src); + make_fpsr(FPU registers[reg]); + break; + case 0x15: /* FLOG10 */ + fpu_debug(("FLOG10 %.04f\n",(double)src)); + FPU registers[reg] = fp_log10 (src); + make_fpsr(FPU registers[reg]); + break; + case 0x16: /* FLOG2 */ + fpu_debug(("FLOG2 %.04f\n",(double)src)); + FPU registers[reg] = fp_log (src) / fp_log (2.0); + make_fpsr(FPU registers[reg]); + break; + case 0x18: /* FABS */ + fpu_debug(("FABS %.04f\n",(double)src)); + FPU registers[reg] = fp_fabs(src); + make_fpsr(FPU registers[reg]); + break; + case 0x19: /* FCOSH */ + fpu_debug(("FCOSH %.04f\n",(double)src)); + FPU registers[reg] = fp_cosh(src); + make_fpsr(FPU registers[reg]); + break; + case 0x1a: /* FNEG */ + fpu_debug(("FNEG %.04f\n",(double)src)); + FPU registers[reg] = -src; + make_fpsr(FPU registers[reg]); + break; + case 0x1c: /* FACOS */ + fpu_debug(("FACOS %.04f\n",(double)src)); + FPU registers[reg] = fp_acos(src); + make_fpsr(FPU registers[reg]); + break; + case 0x1d: /* FCOS */ + fpu_debug(("FCOS %.04f\n",(double)src)); + FPU registers[reg] = fp_cos(src); + make_fpsr(FPU registers[reg]); + break; + case 0x1e: /* FGETEXP */ + fpu_debug(("FGETEXP %.04f\n",(double)src)); + if( isinf(src) ) { + make_nan( FPU registers[reg] ); + } + else { + FPU registers[reg] = fast_fgetexp( src ); + } + make_fpsr(FPU registers[reg]); + break; + case 0x1f: /* FGETMAN */ + fpu_debug(("FGETMAN %.04f\n",(double)src)); + if( src == 0 ) { + FPU registers[reg] = 0; + } + else if( isinf(src) ) { + make_nan( FPU registers[reg] ); + } + else { + FPU registers[reg] = src; + fast_remove_exponent( FPU registers[reg] ); + } + make_fpsr(FPU registers[reg]); + break; + case 0x20: /* FDIV */ + fpu_debug(("FDIV %.04f\n",(double)src)); + FPU registers[reg] /= src; + make_fpsr(FPU registers[reg]); + break; + case 0x21: /* FMOD */ + fpu_debug(("FMOD %.04f\n",(double)src)); + // FPU registers[reg] = FPU registers[reg] - (fpu_register) ((int) (FPU registers[reg] / src)) * src; + { + fpu_register quot = fp_round_to_zero(FPU registers[reg] / src); + uae_u32 sign = get_quotient_sign(FPU registers[reg],src); + FPU registers[reg] = FPU registers[reg] - quot * src; + make_fpsr(FPU registers[reg]); + make_quotient(quot, sign); + } + break; + case 0x23: /* FMUL */ + fpu_debug(("FMUL %.04f\n",(double)src)); + get_dest_flags(FPU registers[reg]); + get_source_flags(src); + if(fl_dest.in_range && fl_source.in_range) { + FPU registers[reg] *= src; + } + else if (fl_dest.nan || fl_source.nan || + fl_dest.zero && fl_source.infinity || + fl_dest.infinity && fl_source.zero ) { + make_nan( FPU registers[reg] ); + } + else if (fl_dest.zero || fl_source.zero ) { + if (fl_dest.negative && !fl_source.negative || + !fl_dest.negative && fl_source.negative) { + make_zero_negative(FPU registers[reg]); + } + else { + make_zero_positive(FPU registers[reg]); + } + } + else { + if( fl_dest.negative && !fl_source.negative || + !fl_dest.negative && fl_source.negative) { + make_inf_negative(FPU registers[reg]); + } + else { + make_inf_positive(FPU registers[reg]); + } + } + make_fpsr(FPU registers[reg]); + break; + case 0x24: /* FSGLDIV */ + fpu_debug(("FSGLDIV %.04f\n",(double)src)); + FPU registers[reg] = (float)(FPU registers[reg] / src); + make_fpsr(FPU registers[reg]); + break; + case 0x25: /* FREM */ + fpu_debug(("FREM %.04f\n",(double)src)); + // FPU registers[reg] = FPU registers[reg] - (double) ((int) (FPU registers[reg] / src + 0.5)) * src; + { + fpu_register quot = fp_round_to_nearest(FPU registers[reg] / src); + uae_u32 sign = get_quotient_sign(FPU registers[reg],src); + FPU registers[reg] = FPU registers[reg] - quot * src; + make_fpsr(FPU registers[reg]); + make_quotient(quot,sign); + } + break; + + case 0x26: /* FSCALE */ + fpu_debug(("FSCALE %.04f\n",(double)src)); + + // TODO: + // Overflow, underflow + + if( isinf(FPU registers[reg]) ) { + make_nan( FPU registers[reg] ); + } + else { + // When the absolute value of the source operand is >= 2^14, + // an overflow or underflow always results. + // Here (int) cast is okay. + fast_scale( FPU registers[reg], (int)fp_round_to_zero(src) ); + } + make_fpsr(FPU registers[reg]); + break; + case 0x27: /* FSGLMUL */ + fpu_debug(("FSGLMUL %.04f\n",(double)src)); + FPU registers[reg] = (float)(FPU registers[reg] * src); + make_fpsr(FPU registers[reg]); + break; + case 0x28: /* FSUB */ + fpu_debug(("FSUB %.04f\n",(double)src)); + FPU registers[reg] -= src; + make_fpsr(FPU registers[reg]); + break; + case 0x22: /* FADD */ + fpu_debug(("FADD %.04f\n",(double)src)); + FPU registers[reg] += src; + make_fpsr(FPU registers[reg]); + break; + case 0x30: /* FSINCOS */ + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + fpu_debug(("FSINCOS %.04f\n",(double)src)); + // Cosine must be calculated first if same register + FPU registers[extra & 7] = fp_cos(src); + FPU registers[reg] = fp_sin (src); + // Set FPU fpsr according to the sine result + make_fpsr(FPU registers[reg]); + break; + case 0x38: /* FCMP */ + fpu_debug(("FCMP %.04f\n",(double)src)); + set_fpsr(0); + make_fpsr(FPU registers[reg] - src); + break; + case 0x3a: /* FTST */ + fpu_debug(("FTST %.04f\n",(double)src)); + set_fpsr(0); + make_fpsr(src); + break; + default: + fpu_debug(("ILLEGAL F OP %X\n",opcode)); + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + break; + } + fpu_debug(("END m68k_getpc()=%X\n",m68k_getpc())); + dump_registers( "END "); + return; + } + + fpu_debug(("ILLEGAL F OP 2 %X\n",opcode)); + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); +} + +/* -------------------------- Initialization -------------------------- */ + +PRIVATE uae_u8 m_fpu_state_original[108]; // 90/94/108 + +PUBLIC void FFPU fpu_init (bool integral_68040) +{ + fpu_debug(("fpu_init\n")); + + static bool initialized_lookup_tables = false; + if (!initialized_lookup_tables) { + fpu_init_native_fflags(); + fpu_init_native_exceptions(); + fpu_init_native_accrued_exceptions(); + initialized_lookup_tables = true; + } + + FPU is_integral = integral_68040; + FPU instruction_address = 0; + FPU fpsr.quotient = 0; + set_fpcr(0); + set_fpsr(0); + +#if defined(FPU_USE_X86_ROUNDING) + // Initial state after boot, reset and frestore(null frame) + x86_control_word = CW_INITIAL; +#elif defined(__i386__) && defined(X86_ASSEMBLY) + volatile unsigned short int cw; + __asm__ __volatile__("fnstcw %0" : "=m" (cw)); + cw &= ~0x0300; cw |= 0x0300; // CW_PC_EXTENDED + cw &= ~0x0C00; cw |= 0x0000; // CW_RC_NEAR + __asm__ __volatile__("fldcw %0" : : "m" (cw)); +#endif + + FPU result = 1; + + for (int i = 0; i < 8; i++) + make_nan(FPU registers[i]); +} + +PUBLIC void FFPU fpu_exit (void) +{ + fpu_debug(("fpu_exit\n")); +} + +PUBLIC void FFPU fpu_reset (void) +{ + fpu_debug(("fpu_reset\n")); + fpu_exit(); + fpu_init(FPU is_integral); +} diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h new file mode 100644 index 00000000..05c17b3a --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h @@ -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 */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp index d5848b45..72cd6e9d 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp +++ b/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp @@ -12,7 +12,7 @@ * The lookup tables did not work correctly, rewritten. * FINT: * (int) cast does not work, fixed. - * Further, now honors the fpcr rounding modes. + * Further, now honors the FPU fpcr rounding modes. * FINTRZ: * (int) cast cannot be used, fixed. * FGETEXP: @@ -25,11 +25,11 @@ * Quotient byte handling was missing. * FSCALE: * Input argument value 0 was not handled correctly. - * FMOVEM Control Registers to/from address registers An: + * FMOVEM Control Registers to/from address FPU registers An: * A bug caused the code never been called. * FMOVEM Control Registers pre-decrement: * Moving of control regs from memory to FPP was not handled properly, - * if not all of the three registers were moved. + * if not all of the three FPU registers were moved. * Condition code "Not Greater Than or Equal": * Returned erroneous value. * FSINCOS: @@ -46,13 +46,13 @@ * get_fp_value: * Immediate addressing mode && Operation Length == Byte -> * Use the low-order byte of the extension word. - * Now fpcr high 16 bits are always read as zeroes, no matter what was + * Now FPU fpcr high 16 bits are always read as zeroes, no matter what was * written to them. * * Other: * - Optimized single/double/extended to/from conversion functions. * Huge speed boost, but not (necessarily) portable to other systems. - * Enabled/disabled by #define HAVE_IEEE_DOUBLE 1 + * Enabled/disabled by #define FPU_HAVE_IEEE_DOUBLE 1 * - Optimized versions of FSCALE, FGETEXP, FGETMAN * - Conversion routines now handle NaN and infinity better. * - Some constants precalculated. Not all compilers can optimize the @@ -61,41 +61,74 @@ * TODO: * - Floating point exceptions. * - More Infinity/NaN/overflow/underflow checking. - * - FPIAR (only needed when exceptions are implemented) + * - FPU instruction_address (only needed when exceptions are implemented) * - Should be written in assembly to support long doubles. * - Precision rounding single/double */ #include "sysdeps.h" - #include #include - #include "memory.h" #include "readcpu.h" #include "newcpu.h" #include "main.h" +#define FPU_IMPLEMENTATION +#include "fpu/fpu.h" +#include "fpu/fpu_uae.h" -#define DEBUG 0 -#include "debug.h" +/* Global FPU context */ +fpu_t fpu; +/* -------------------------------------------------------------------------- */ +/* --- Native Support --- */ +/* -------------------------------------------------------------------------- */ -// Only define if you have IEEE 64 bit doubles. -#define HAVE_IEEE_DOUBLE 1 +#include "fpu/flags.h" +#include "fpu/exceptions.h" +#include "fpu/rounding.h" +#include "fpu/impl.h" -#ifdef WORDS_BIGENDIAN -#define FLO 1 -#define FHI 0 -#else -#define FLO 0 -#define FHI 1 -#endif +#include "fpu/flags.cpp" +#include "fpu/exceptions.cpp" -// fpcr rounding modes -#define ROUND_TO_NEAREST 0 -#define ROUND_TO_ZERO 0x10 -#define ROUND_TO_NEGATIVE_INFINITY 0x20 -#define ROUND_TO_POSITIVE_INFINITY 0x30 +/* -------------------------------------------------------------------------- */ +/* --- Scopes Definition --- */ +/* -------------------------------------------------------------------------- */ + +#undef PUBLIC +#define PUBLIC /**/ + +#undef PRIVATE +#define PRIVATE static + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + +/* -------------------------------------------------------------------------- */ +/* --- Debugging --- */ +/* -------------------------------------------------------------------------- */ + +PUBLIC void FFPU fpu_dump_registers(void) +{ + for (int i = 0; i < 8; i++){ + printf ("FP%d: %g ", i, fpu_get_register(i)); + if ((i & 3) == 3) + printf ("\n"); + } +} + +PUBLIC void FFPU fpu_dump_flags(void) +{ + printf ("N=%d Z=%d I=%d NAN=%d\n", + (get_fpsr() & FPSR_CCB_NEGATIVE) != 0, + (get_fpsr() & FPSR_CCB_ZERO)!= 0, + (get_fpsr() & FPSR_CCB_INFINITY) != 0, + (get_fpsr() & FPSR_CCB_NAN) != 0); +} /* single : S 8*E 23*F */ /* double : S 11*E 52*F */ @@ -105,185 +138,183 @@ /* E = MAX & F # 0 -> NotANumber */ /* E = biased by 127 (single) ,1023 (double) ,16383 (extended) */ +#if FPU_DEBUG -#if DEBUG - -#define CONDRET(s,x) D(bug("fpp_cond %s = %d\r\n",s,(uint32)(x))); return (x) - -static void dump_fp_regs( char *s ) +PUBLIC void FFPU dump_registers(const char * str) { - char b[512]; + char temp_str[512]; - sprintf( - b, - "%s: %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f\r\n", - s, - (float)regs.fp[0], - (float)regs.fp[1], - (float)regs.fp[2], - (float)regs.fp[3], - (float)regs.fp[4], - (float)regs.fp[5], - (float)regs.fp[6], - (float)regs.fp[7] - ); - D(bug((char*)b)); + sprintf(temp_str, "%s: %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f\n", + str, + get_register(0), get_register(1), get_register(2), get_register(3), + get_register(4), get_register(5), get_register(6), get_register(7) ); + + fpu_debug((temp_str)); } -static void dump_first_bytes( uint8 *buf, int32 actual ) +PUBLIC void FFPU dump_first_bytes(uae_u8 * buffer, uae_s32 actual) { - char b[256], bb[10]; - int32 i, bytes = sizeof(b)/3-1-3; + char temp_buf1[256], temp_buf2[10]; + int bytes = sizeof(temp_buf1)/3-1-3; if (actual < bytes) bytes = actual; - - *b = 0; - for (i=0; i> 20; + uae_u32 * const p = (uae_u32 *)&r; + int exp = (p[FHI] & 0x7FF00000) >> 20; // TODO: overflow flags exp += add; if(exp >= 2047) { - MAKE_INF_POSITIVE(p); + make_inf_positive(r); } else if(exp < 0) { // keep sign (+/- 0) p[FHI] &= 0x80000000; @@ -292,41 +323,45 @@ static __inline__ void FAST_SCALE(uae_u32 *p, int add) } } -static __inline__ double FAST_FGETEXP(uae_u32 *p) +PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r) { + uae_u32 * const p = (uae_u32 *)&r; int exp = (p[FHI] & 0x7FF00000) >> 20; return( exp - 1023 ); } // Normalize to range 1..2 -static __inline__ void FAST_REMOVE_EXPONENT(uae_u32 *p) +PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r) { + uae_u32 * const p = (uae_u32 *)&r; p[FHI] = (p[FHI] & 0x800FFFFF) | 0x3FF00000; } // The sign of the quotient is the exclusive-OR of the sign bits // of the source and destination operands. -static __inline__ uae_u32 GET_QUOTIENT_SIGN(uae_u32 *a, uae_u32 *b) +PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_register const & rb) { - return( ((a[FHI] ^ b[FHI]) & 0x80000000) ? 0x800000 : 0); + uae_u32 * const a = (uae_u32 *)&ra; + uae_u32 * const b = (uae_u32 *)&rb; + return (((a[FHI] ^ b[FHI]) & 0x80000000) ? FPSR_QUOTIENT_SIGN : 0); } // Quotient Byte is loaded with the sign and least significant // seven bits of the quotient. -static __inline__ uae_u32 MAKE_QUOTIENT( uae_u32 fpsr, double quot, uae_u32 sign ) +PRIVATE inline void FFPU make_quotient(fpu_register const & quotient, uae_u32 sign) { - uae_u32 lsb = (uae_u32)fabs(quot) & 0x7F; - return (fpsr & 0xFF00FFFF) | sign | (lsb << 16); + uae_u32 lsb = (uae_u32)fabs(quotient) & 0x7f; + FPU fpsr.quotient = sign | (lsb << 16); } -static __inline__ double to_single (uae_u32 value) +// to_single +PRIVATE inline fpu_register FFPU make_single(uae_u32 value) { - double result; - uae_u32 *p; - - if ((value & 0x7fffffff) == 0) return (0.0); - - p = (uae_u32 *)&result; + if ((value & 0x7fffffff) == 0) + return (0.0); + + fpu_register result; + uae_u32 * p = (uae_u32 *)&result; uae_u32 sign = (value & 0x80000000); uae_u32 exp = ((value & 0x7F800000) >> 23) + 1023 - 127; @@ -334,18 +369,20 @@ static __inline__ double to_single (uae_u32 value) p[FLO] = value << 29; p[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); - D(bug("to_single (%X) = %.04f\r\n",value,(float)result)); - + fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); + return(result); } -static __inline__ uae_u32 from_single (double src) +// from_single +PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) { + if (src == 0.0) + return 0; + uae_u32 result; uae_u32 *p = (uae_u32 *)&src; - if (src == 0.0) return 0; - uae_u32 sign = (p[FHI] & 0x80000000); uae_u32 exp = (p[FHI] & 0x7FF00000) >> 20; @@ -359,24 +396,26 @@ static __inline__ uae_u32 from_single (double src) result = sign | (exp << 23) | ((p[FHI] & 0x000FFFFF) << 3) | (p[FLO] >> 29); - D(bug("from_single (%.04f) = %X\r\n",(float)src,result)); + fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result)); - return (result); + return (result); } -static __inline__ double to_exten(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) +// to_exten +PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) { - double result; + if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) + return 0.0; + + fpu_register result; uae_u32 *p = (uae_u32 *)&result; - - if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) return 0.0; - + uae_u32 sign = wrd1 & 0x80000000; uae_u32 exp = (wrd1 >> 16) & 0x7fff; // The explicit integer bit is not set, must normalize. if((wrd2 & 0x80000000) == 0) { - D(bug("to_exten denormalized mantissa (%X,%X,%X)\r\n",wrd1,wrd2,wrd3)); + fpu_debug(("make_extended denormalized mantissa (%X,%X,%X)\n",wrd1,wrd2,wrd3)); if( wrd2 | wrd3 ) { // mantissa, not fraction. uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3; @@ -410,7 +449,7 @@ static __inline__ double to_exten(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) p[FLO] = (wrd2 << 21) | (wrd3 >> 11); p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); - D(bug("to_exten (%X,%X,%X) = %.04f\r\n",wrd1,wrd2,wrd3,(float)result)); + fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); return(result); } @@ -419,27 +458,25 @@ static __inline__ double to_exten(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) Would be so much easier with full size floats :( ... this is so vague. */ -static __inline__ void to_exten_no_normalize( - uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, uae_u32 *p +// make_extended_no_normalize +PRIVATE inline void FFPU make_extended_no_normalize( + uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result ) { - // double result; - // uae_u32 *p = (uae_u32 *)&result; - // Is it zero? - if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { - MAKE_ZERO_POSITIVE(p); + if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { + make_zero_positive(result); return; } // Is it NaN? if( (wrd1 & 0x7FFF0000) == 0x7FFF0000 ) { if( (wrd1 & 0x0000FFFF) || wrd2 || wrd3 ) { - MAKE_NAN( p ); + make_nan(result); return; } } - + uae_u32 sign = wrd1 & 0x80000000; uae_u32 exp = (wrd1 >> 16) & 0x7fff; @@ -454,24 +491,26 @@ static __inline__ void to_exten_no_normalize( } // drop the explicit integer bit. + uae_u32 *p = (uae_u32 *)&result; p[FLO] = (wrd2 << 21) | (wrd3 >> 11); p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); - D(bug("to_exten (%X,%X,%X) = %.04f\r\n",wrd1,wrd2,wrd3,(float)(*(double *)p))); - - // return(result); + fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(float)(*(double *)p))); } -static __inline__ void from_exten(double src, 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 +) { - uae_u32 *p = (uae_u32 *)&src; - if (src == 0.0) { *wrd1 = *wrd2 = *wrd3 = 0; return; - } - - D(bug("from_exten (%X,%X)\r\n",p[FLO],p[FHI])); + } + + uae_u32 *p = (uae_u32 *)&src; + + fpu_debug(("extract_extended (%X,%X)\n",p[FLO],p[FHI])); uae_u32 sign = p[FHI] & 0x80000000; @@ -488,26 +527,29 @@ static __inline__ void from_exten(double src, uae_u32 * wrd1, uae_u32 * wrd2, ua *wrd2 = 0x80000000 | ((p[FHI] & 0x000FFFFF) << 11) | ((p[FLO] & 0xFFE00000) >> 21); *wrd3 = p[FLO] << 11; - D(bug("from_exten (%.04f) = %X,%X,%X\r\n",(float)src,*wrd1,*wrd2,*wrd3)); + fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); } -static __inline__ double to_double(uae_u32 wrd1, uae_u32 wrd2) +// to_double +PRIVATE inline fpu_register FFPU make_double(uae_u32 wrd1, uae_u32 wrd2) { - double result; - uae_u32 *p; - - if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0) return 0.0; - - p = (uae_u32 *)&result; + if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0) + return 0.0; + + fpu_register result; + uae_u32 *p = (uae_u32 *)&result; p[FLO] = wrd2; p[FHI] = wrd1; - D(bug("to_double (%X,%X) = %.04f\r\n",wrd1,wrd2,(float)result)); + fpu_debug(("make_double (%X,%X) = %.04f\n",wrd1,wrd2,(double)result)); return(result); } -static __inline__ void from_double(double src, uae_u32 * wrd1, uae_u32 * wrd2) +// from_double +PRIVATE inline void FFPU extract_double(fpu_register const & src, + uae_u32 * wrd1, uae_u32 * wrd2 +) { /* if (src == 0.0) { @@ -519,40 +561,45 @@ static __inline__ void from_double(double src, uae_u32 * wrd1, uae_u32 * wrd2) *wrd2 = p[FLO]; *wrd1 = p[FHI]; - D(bug("from_double (%.04f) = %X,%X\r\n",(float)src,*wrd1,*wrd2)); + fpu_debug(("extract_double (%.04f) = %X,%X\n",(double)src,*wrd1,*wrd2)); } +#else // !FPU_HAVE_IEEE_DOUBLE - -#else // !HAVE_IEEE_DOUBLE - - -#define MAKE_FPSR(fpsr,r) fpsr = (fpsr & 0x00FFFFFF) | (r == 0 ? 0x4000000 : 0) | (r < 0 ? 0x8000000 : 0) - - -static __inline__ double to_single (uae_u32 value) +#ifndef FPU_USE_NATIVE_FLAGS +PRIVATE inline void FFPU make_fpsr(fpu_register const & r) { - double frac, result; + FPU fpsr.condition_codes + = ((r == 0.0) ? NATIVE_FFLAG_ZERO : 0) + | ((r < 0.0) ? NATIVE_FFLAG_NEGATIVE : 0) + ; +} +#endif +// make_single +PRIVATE inline fpu_register FFPU make_single(uae_u32 value) +{ if ((value & 0x7fffffff) == 0) return (0.0); - frac = (double) ((value & 0x7fffff) | 0x800000) / 8388608.0; + + fpu_register frac = (fpu_register) ((value & 0x7fffff) | 0x800000) / 8388608.0; if (value & 0x80000000) frac = -frac; - result = ldexp (frac, (int)((value >> 23) & 0xff) - 127); - - D(bug("to_single (%X) = %.04f\r\n",value,(float)result)); - + + fpu_register result = ldexp (frac, (int)((value >> 23) & 0xff) - 127); + fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); + return (result); } -static __inline__ uae_u32 from_single (double src) +// extract_single +PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) { int expon; uae_u32 tmp, result; - double frac; -#if DEBUG - double src0 = src; + fpu_register frac; +#if FPU_DEBUG + fpu_register src0 = src; #endif if (src == 0.0) @@ -571,187 +618,195 @@ static __inline__ uae_u32 from_single (double src) } result = tmp | (((expon + 127 - 1) & 0xff) << 23) | (((int) (frac * 16777216.0)) & 0x7fffff); - // D(bug("from_single (%.04f) = %X\r\n",(float)src0,result)); + // fpu_debug(("extract_single (%.04f) = %X\n",(float)src0,result)); return (result); } -static __inline__ double to_exten(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) +// to exten +PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) { - double frac, result; + fpu_register frac, result; - if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) + if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) return 0.0; - frac = (double) wrd2 / 2147483648.0 + - (double) wrd3 / 9223372036854775808.0; - if (wrd1 & 0x80000000) + frac = (fpu_register) wrd2 / 2147483648.0 + + (fpu_register) wrd3 / 9223372036854775808.0; + if (wrd1 & 0x80000000) frac = -frac; - result = ldexp (frac, (int)((wrd1 >> 16) & 0x7fff) - 16383); + result = ldexp (frac, (int)((wrd1 >> 16) & 0x7fff) - 16383); - D(bug("to_exten (%X,%X,%X) = %.04f\r\n",wrd1,wrd2,wrd3,(float)result)); + fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); - return result; + return result; } -static __inline__ void from_exten(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) +// extract_extended +PRIVATE inline void FFPU extract_extended(fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) { - int expon; - double frac; -#if DEBUG - double src0 = src; + int expon; + fpu_register frac; +#if FPU_DEBUG + fpu_register src0 = src; #endif - if (src == 0.0) { + if (src == 0.0) { *wrd1 = 0; *wrd2 = 0; *wrd3 = 0; return; - } - if (src < 0) { + } + if (src < 0) { *wrd1 = 0x80000000; src = -src; - } else { + } else { *wrd1 = 0; - } - frac = frexp (src, &expon); - frac += 0.5 / 18446744073709551616.0; - if (frac >= 1.0) { + } + frac = frexp (src, &expon); + frac += 0.5 / 18446744073709551616.0; + if (frac >= 1.0) { frac /= 2.0; expon++; - } - *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16); - *wrd2 = (uae_u32) (frac * 4294967296.0); - *wrd3 = (uae_u32) (frac * 18446744073709551616.0 - *wrd2 * 4294967296.0); + } + *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16); + *wrd2 = (uae_u32) (frac * 4294967296.0); + *wrd3 = (uae_u32) (frac * 18446744073709551616.0 - *wrd2 * 4294967296.0); - // D(bug("from_exten (%.04f) = %X,%X,%X\r\n",(float)src0,*wrd1,*wrd2,*wrd3)); + // fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(float)src0,*wrd1,*wrd2,*wrd3)); } -static __inline__ double to_double(uae_u32 wrd1, uae_u32 wrd2) +// make_double +PRIVATE inline fpu_register FFPU make_double(uae_u32 wrd1, uae_u32 wrd2) { - double frac, result; - - if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0) + if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0) return 0.0; - frac = (double) ((wrd1 & 0xfffff) | 0x100000) / 1048576.0 + - (double) wrd2 / 4503599627370496.0; - if (wrd1 & 0x80000000) + + fpu_register frac = + (fpu_register) ((wrd1 & 0xfffff) | 0x100000) / 1048576.0 + + (fpu_register) wrd2 / 4503599627370496.0; + + if (wrd1 & 0x80000000) frac = -frac; - result = ldexp (frac, (int)((wrd1 >> 20) & 0x7ff) - 1023); + + fpu_register result = ldexp (frac, (int)((wrd1 >> 20) & 0x7ff) - 1023); + fpu_debug(("make_double (%X,%X) = %.04f\n",wrd1,wrd2,(double)result)); - D(bug("to_double (%X,%X) = %.04f\r\n",wrd1,wrd2,(float)result)); - - return result; + return result; } -static __inline__ void from_double(double src, uae_u32 * wrd1, uae_u32 * wrd2) +// extract_double +PRIVATE inline void FFPU extract_double(fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2) { - int expon; - int tmp; - double frac; -#if DEBUG - double src0 = src; + int expon; + int tmp; + fpu_register frac frac; +#if FPU_DEBUG + fpu_register src0 = src; #endif - if (src == 0.0) { + if (src == 0.0) { *wrd1 = 0; *wrd2 = 0; return; - } - if (src < 0) { + } + if (src < 0) { *wrd1 = 0x80000000; src = -src; - } else { + } else { *wrd1 = 0; - } - frac = frexp (src, &expon); - frac += 0.5 / 9007199254740992.0; - if (frac >= 1.0) { + } + frac = frexp (src, &expon); + frac += 0.5 / 9007199254740992.0; + if (frac >= 1.0) { frac /= 2.0; expon++; - } - tmp = (uae_u32) (frac * 2097152.0); - *wrd1 |= (((expon + 1023 - 1) & 0x7ff) << 20) | (tmp & 0xfffff); - *wrd2 = (uae_u32) (frac * 9007199254740992.0 - tmp * 4294967296.0); + } + tmp = (uae_u32) (frac * 2097152.0); + *wrd1 |= (((expon + 1023 - 1) & 0x7ff) << 20) | (tmp & 0xfffff); + *wrd2 = (uae_u32) (frac * 9007199254740992.0 - tmp * 4294967296.0); - // D(bug("from_double (%.04f) = %X,%X\r\n",(float)src0,*wrd1,*wrd2)); -} -#endif // HAVE_IEEE_DOUBLE - -static __inline__ double to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) -{ - double d; - char *cp; - char str[100]; - - cp = str; - if (wrd1 & 0x80000000) - *cp++ = '-'; - *cp++ = (char)((wrd1 & 0xf) + '0'); - *cp++ = '.'; - *cp++ = (char)(((wrd2 >> 28) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 24) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 20) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 16) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 12) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 8) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 4) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 0) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 28) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 24) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 20) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 16) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 12) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 8) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 4) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 0) & 0xf) + '0'); - *cp++ = 'E'; - if (wrd1 & 0x40000000) - *cp++ = '-'; - *cp++ = (char)(((wrd1 >> 24) & 0xf) + '0'); - *cp++ = (char)(((wrd1 >> 20) & 0xf) + '0'); - *cp++ = (char)(((wrd1 >> 16) & 0xf) + '0'); - *cp = 0; - sscanf(str, "%le", &d); - - D(bug("to_pack str = %s\r\n",str)); - - D(bug("to_pack(%X,%X,%X) = %.04f\r\n",wrd1,wrd2,wrd3,(float)d)); - return d; + // fpu_debug(("extract_double (%.04f) = %X,%X\n",(float)src0,*wrd1,*wrd2)); } -static __inline__ void from_pack(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) +#endif + +// to_pack +PRIVATE inline fpu_register FFPU make_packed(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) { - int i; - int t; - char *cp; - char str[100]; + fpu_double d; + char *cp; + char str[100]; - sprintf(str, "%.16e", src); + cp = str; + if (wrd1 & 0x80000000) + *cp++ = '-'; + *cp++ = (char)((wrd1 & 0xf) + '0'); + *cp++ = '.'; + *cp++ = (char)(((wrd2 >> 28) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 16) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 12) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 8) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 4) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 0) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 28) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 16) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 12) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 8) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 4) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 0) & 0xf) + '0'); + *cp++ = 'E'; + if (wrd1 & 0x40000000) + *cp++ = '-'; + *cp++ = (char)(((wrd1 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd1 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd1 >> 16) & 0xf) + '0'); + *cp = 0; + sscanf(str, "%le", &d); - D(bug("from_pack(%.04f,%s)\r\n",(float)src,str)); + fpu_debug(("make_packed str = %s\n",str)); - cp = str; - *wrd1 = *wrd2 = *wrd3 = 0; - if (*cp == '-') { + fpu_debug(("make_packed(%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)d)); + return d; +} + +// from_pack +PRIVATE inline void FFPU extract_packed(fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) +{ + int i; + int t; + char *cp; + char str[100]; + + sprintf(str, "%.16e", src); + + fpu_debug(("extract_packed(%.04f,%s)\n",(double)src,str)); + + cp = str; + *wrd1 = *wrd2 = *wrd3 = 0; + if (*cp == '-') { cp++; *wrd1 = 0x80000000; - } - if (*cp == '+') + } + if (*cp == '+') cp++; - *wrd1 |= (*cp++ - '0'); - if (*cp == '.') + *wrd1 |= (*cp++ - '0'); + if (*cp == '.') cp++; - for (i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) { *wrd2 <<= 4; if (*cp >= '0' && *cp <= '9') - *wrd2 |= *cp++ - '0'; - } - for (i = 0; i < 8; i++) { + *wrd2 |= *cp++ - '0'; + } + for (i = 0; i < 8; i++) { *wrd3 <<= 4; if (*cp >= '0' && *cp <= '9') - *wrd3 |= *cp++ - '0'; - } - if (*cp == 'e' || *cp == 'E') { + *wrd3 |= *cp++ - '0'; + } + if (*cp == 'e' || *cp == 'E') { cp++; if (*cp == '-') { cp++; @@ -765,444 +820,425 @@ static __inline__ void from_pack(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae t = (t << 4) | (*cp++ - '0'); } *wrd1 |= t << 16; - } + } - D(bug("from_pack(%.04f) = %X,%X,%X\r\n",(float)src,*wrd1,*wrd2,*wrd3)); + fpu_debug(("extract_packed(%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); } -static __inline__ int get_fp_value (uae_u32 opcode, uae_u16 extra, double *src) +PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_register & src) { - uaecptr tmppc; - uae_u16 tmp; - int size; - int mode; - int reg; - uae_u32 ad = 0; - static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; - static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; + uaecptr tmppc; + uae_u16 tmp; + int size; + int mode; + int reg; + uae_u32 ad = 0; + static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; + static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; - // D(bug("get_fp_value(%X,%X)\r\n",(int)opcode,(int)extra)); + // fpu_debug(("get_fp_value(%X,%X)\n",(int)opcode,(int)extra)); // dump_first_bytes( regs.pc_p-4, 16 ); - if ((extra & 0x4000) == 0) { - *src = regs.fp[(extra >> 10) & 7]; + if ((extra & 0x4000) == 0) { + src = FPU registers[(extra >> 10) & 7]; return 1; - } - mode = (opcode >> 3) & 7; - reg = opcode & 7; - size = (extra >> 10) & 7; + } + mode = (opcode >> 3) & 7; + reg = opcode & 7; + size = (extra >> 10) & 7; - D(bug("get_fp_value mode=%d, reg=%d, size=%d\r\n",(int)mode,(int)reg,(int)size)); + fpu_debug(("get_fp_value mode=%d, reg=%d, size=%d\n",(int)mode,(int)reg,(int)size)); - switch (mode) { - case 0: - switch (size) { - case 6: - *src = (double) (uae_s8) m68k_dreg (regs, reg); - break; - case 4: - *src = (double) (uae_s16) m68k_dreg (regs, reg); - break; - case 0: - *src = (double) (uae_s32) m68k_dreg (regs, reg); - break; - case 1: - *src = to_single(m68k_dreg (regs, reg)); - break; - default: - return 0; - } - return 1; - case 1: + switch (mode) { + case 0: + switch (size) { + case 6: + src = (fpu_register) (uae_s8) m68k_dreg (regs, reg); + break; + case 4: + src = (fpu_register) (uae_s16) m68k_dreg (regs, reg); + break; + case 0: + src = (fpu_register) (uae_s32) m68k_dreg (regs, reg); + break; + case 1: + src = make_single(m68k_dreg (regs, reg)); + break; + default: return 0; - case 2: - ad = m68k_areg (regs, reg); + } + return 1; + case 1: + return 0; + case 2: + ad = m68k_areg (regs, reg); + break; + case 3: + ad = m68k_areg (regs, reg); + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + break; + case 4: + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + ad = m68k_areg (regs, reg); + break; + case 5: + ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + break; + case 6: + ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch (reg) { + case 0: + ad = (uae_s32) (uae_s16) next_iword(); break; - case 3: - ad = m68k_areg (regs, reg); - m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + case 1: + ad = next_ilong(); break; - case 4: - m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; - ad = m68k_areg (regs, reg); + case 2: + ad = m68k_getpc (); + ad += (uae_s32) (uae_s16) next_iword(); + fpu_debug(("get_fp_value next_iword()=%X\n",ad-m68k_getpc()-2)); break; - case 5: - ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + case 3: + tmppc = m68k_getpc (); + tmp = (uae_u16)next_iword(); + ad = get_disp_ea_020 (tmppc, tmp); break; - case 6: - ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); - break; - case 7: - switch (reg) { - case 0: - ad = (uae_s32) (uae_s16) next_iword(); - break; - case 1: - ad = next_ilong(); - break; - case 2: - ad = m68k_getpc (); - ad += (uae_s32) (uae_s16) next_iword(); - D(bug("get_fp_value next_iword()=%X\r\n",ad-m68k_getpc()-2)); - break; - case 3: - tmppc = m68k_getpc (); - tmp = (uae_u16)next_iword(); - ad = get_disp_ea_020 (tmppc, tmp); - break; - case 4: - ad = m68k_getpc (); - m68k_setpc (ad + sz2[size]); - // Immediate addressing mode && Operation Length == Byte -> - // Use the low-order byte of the extension word. - if(size == 6) ad++; - break; - default: - return 0; - } - } + case 4: + ad = m68k_getpc (); + m68k_setpc (ad + sz2[size]); + // Immediate addressing mode && Operation Length == Byte -> + // Use the low-order byte of the extension word. + if(size == 6) ad++; + break; + default: + return 0; + } + } - D(bug("get_fp_value m68k_getpc()=%X\r\n",m68k_getpc())); - D(bug("get_fp_value ad=%X\r\n",ad)); - D(bug("get_fp_value get_long (ad)=%X\r\n",get_long (ad))); + fpu_debug(("get_fp_value m68k_getpc()=%X\n",m68k_getpc())); + fpu_debug(("get_fp_value ad=%X\n",ad)); + fpu_debug(("get_fp_value get_long (ad)=%X\n",get_long (ad))); dump_first_bytes( get_real_address(ad)-64, 64 ); dump_first_bytes( get_real_address(ad), 64 ); - switch (size) { - case 0: - *src = (double) (uae_s32) get_long (ad); - break; - case 1: - *src = to_single(get_long (ad)); - break; - - case 2:{ - uae_u32 wrd1, wrd2, wrd3; - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - ad += 4; - wrd3 = get_long (ad); - *src = to_exten(wrd1, wrd2, wrd3); - } - break; - case 3:{ - uae_u32 wrd1, wrd2, wrd3; - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - ad += 4; - wrd3 = get_long (ad); - *src = to_pack(wrd1, wrd2, wrd3); - } - break; - case 4: - *src = (double) (uae_s16) get_word(ad); - break; - case 5:{ - uae_u32 wrd1, wrd2; - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - *src = to_double(wrd1, wrd2); - } - break; - case 6: - *src = (double) (uae_s8) get_byte(ad); - break; - default: - return 0; - } - - // D(bug("get_fp_value result = %.04f\r\n",(float)*src)); - - return 1; + switch (size) { + case 0: + src = (fpu_register) (uae_s32) get_long (ad); + break; + case 1: + src = make_single(get_long (ad)); + break; + case 2: { + uae_u32 wrd1, wrd2, wrd3; + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + src = make_extended(wrd1, wrd2, wrd3); + break; + } + case 3: { + uae_u32 wrd1, wrd2, wrd3; + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + src = make_packed(wrd1, wrd2, wrd3); + break; + } + case 4: + src = (fpu_register) (uae_s16) get_word(ad); + break; + case 5: { + uae_u32 wrd1, wrd2; + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + src = make_double(wrd1, wrd2); + break; + } + case 6: + src = (fpu_register) (uae_s8) get_byte(ad); + break; + default: + return 0; + } + + // fpu_debug(("get_fp_value result = %.04f\n",(float)src)); + return 1; } -static __inline__ int put_fp_value (double value, uae_u32 opcode, uae_u16 extra) +PRIVATE inline int FFPU put_fp_value (uae_u32 opcode, uae_u16 extra, fpu_register const & value) { - uae_u16 tmp; - uaecptr tmppc; - int size; - int mode; - int reg; - uae_u32 ad; - static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; - static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; + uae_u16 tmp; + uaecptr tmppc; + int size; + int mode; + int reg; + uae_u32 ad; + static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; + static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; - // D(bug("put_fp_value(%.04f,%X,%X)\r\n",(float)value,(int)opcode,(int)extra)); + // fpu_debug(("put_fp_value(%.04f,%X,%X)\n",(float)value,(int)opcode,(int)extra)); - if ((extra & 0x4000) == 0) { + if ((extra & 0x4000) == 0) { int dest_reg = (extra >> 10) & 7; - regs.fp[dest_reg] = value; - MAKE_FPSR(regs.fpsr,regs.fp[dest_reg]); + FPU registers[dest_reg] = value; + make_fpsr(FPU registers[dest_reg]); return 1; - } - mode = (opcode >> 3) & 7; - reg = opcode & 7; - size = (extra >> 10) & 7; - ad = 0xffffffff; - switch (mode) { - case 0: - switch (size) { - case 6: - m68k_dreg (regs, reg) = (((int) value & 0xff) - | (m68k_dreg (regs, reg) & ~0xff)); - break; - case 4: - m68k_dreg (regs, reg) = (((int) value & 0xffff) - | (m68k_dreg (regs, reg) & ~0xffff)); - break; - case 0: - m68k_dreg (regs, reg) = (int) value; - break; - case 1: - m68k_dreg (regs, reg) = from_single(value); - break; - default: - return 0; - } - return 1; - case 1: - return 0; - case 2: - ad = m68k_areg (regs, reg); - break; - case 3: - ad = m68k_areg (regs, reg); - m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; - break; - case 4: - m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; - ad = m68k_areg (regs, reg); - break; - case 5: - ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); - break; - case 6: - ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); - break; - case 7: - switch (reg) { - case 0: - ad = (uae_s32) (uae_s16) next_iword(); - break; - case 1: - ad = next_ilong(); - break; - case 2: - ad = m68k_getpc (); - ad += (uae_s32) (uae_s16) next_iword(); - break; - case 3: - tmppc = m68k_getpc (); - tmp = (uae_u16)next_iword(); - ad = get_disp_ea_020 (tmppc, tmp); - break; - case 4: - ad = m68k_getpc (); - m68k_setpc (ad + sz2[size]); - break; - default: - return 0; - } - } - switch (size) { - case 0: - put_long (ad, (uae_s32) value); - break; - case 1: - put_long (ad, from_single(value)); - break; - case 2: - { - uae_u32 wrd1, wrd2, wrd3; - from_exten(value, &wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); - } - break; - case 3: - { - uae_u32 wrd1, wrd2, wrd3; - from_pack(value, &wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); - } + } + mode = (opcode >> 3) & 7; + reg = opcode & 7; + size = (extra >> 10) & 7; + ad = 0xffffffff; + switch (mode) { + case 0: + switch (size) { + case 6: + m68k_dreg (regs, reg) + = (((uae_s32) value & 0xff) + | (m68k_dreg (regs, reg) & ~0xff)); break; case 4: - put_word(ad, (uae_s16) value); + m68k_dreg (regs, reg) + = (((uae_s32) value & 0xffff) + | (m68k_dreg (regs, reg) & ~0xffff)); break; - case 5:{ - uae_u32 wrd1, wrd2; - from_double(value, &wrd1, &wrd2); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - } + case 0: + m68k_dreg (regs, reg) = (uae_s32) value; break; - case 6: - put_byte(ad, (uae_s8) value); + case 1: + m68k_dreg (regs, reg) = extract_single(value); break; - default: + default: return 0; - } - return 1; -} - -static __inline__ int get_fp_ad(uae_u32 opcode, uae_u32 * ad) -{ - uae_u16 tmp; - uaecptr tmppc; - int mode; - int reg; - - mode = (opcode >> 3) & 7; - reg = opcode & 7; - switch (mode) { - case 0: - case 1: + } + return 1; + case 1: + return 0; + case 2: + ad = m68k_areg (regs, reg); + break; + case 3: + ad = m68k_areg (regs, reg); + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + break; + case 4: + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + ad = m68k_areg (regs, reg); + break; + case 5: + ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + break; + case 6: + ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch (reg) { + case 0: + ad = (uae_s32) (uae_s16) next_iword(); + break; + case 1: + ad = next_ilong(); + break; + case 2: + ad = m68k_getpc (); + ad += (uae_s32) (uae_s16) next_iword(); + break; + case 3: + tmppc = m68k_getpc (); + tmp = (uae_u16)next_iword(); + ad = get_disp_ea_020 (tmppc, tmp); + break; + case 4: + ad = m68k_getpc (); + m68k_setpc (ad + sz2[size]); + break; + default: return 0; - case 2: - *ad = m68k_areg (regs, reg); - break; - case 3: - *ad = m68k_areg (regs, reg); - break; - case 4: - *ad = m68k_areg (regs, reg); - break; - case 5: - *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); - break; - case 6: - *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); - break; - case 7: - switch (reg) { - case 0: - *ad = (uae_s32) (uae_s16) next_iword(); - break; - case 1: - *ad = next_ilong(); - break; - case 2: - *ad = m68k_getpc (); - *ad += (uae_s32) (uae_s16) next_iword(); - break; - case 3: - tmppc = m68k_getpc (); - tmp = (uae_u16)next_iword(); - *ad = get_disp_ea_020 (tmppc, tmp); - break; - default: - return 0; - } - } - return 1; -} - -static __inline__ int fpp_cond(uae_u32 opcode, int condition) -{ -#define N ((regs.fpsr & 0x8000000) != 0) -#define Z ((regs.fpsr & 0x4000000) != 0) -#define I ((regs.fpsr & 0x2000000) != 0) -#define NotANumber ((regs.fpsr & 0x1000000) != 0) - - switch (condition) { - case 0x00: - CONDRET("False",0); - case 0x01: - CONDRET("Equal",Z); - case 0x02: - CONDRET("Ordered Greater Than",!(NotANumber || Z || N)); - case 0x03: - CONDRET("Ordered Greater Than or Equal",Z || !(NotANumber || N)); - case 0x04: - CONDRET("Ordered Less Than",N && !(NotANumber || Z)); - case 0x05: - CONDRET("Ordered Less Than or Equal",Z || (N && !NotANumber)); - case 0x06: - CONDRET("Ordered Greater or Less Than",!(NotANumber || Z)); - case 0x07: - CONDRET("Ordered",!NotANumber); - case 0x08: - CONDRET("Unordered",NotANumber); - case 0x09: - CONDRET("Unordered or Equal",NotANumber || Z); - case 0x0a: - CONDRET("Unordered or Greater Than",NotANumber || !(N || Z)); - case 0x0b: - CONDRET("Unordered or Greater or Equal",NotANumber || Z || !N); - case 0x0c: - CONDRET("Unordered or Less Than",NotANumber || (N && !Z)); - case 0x0d: - CONDRET("Unordered or Less or Equal",NotANumber || Z || N); - case 0x0e: - CONDRET("Not Equal",!Z); - case 0x0f: - CONDRET("True",1); - case 0x10: - CONDRET("Signaling False",0); - case 0x11: - CONDRET("Signaling Equal",Z); - case 0x12: - CONDRET("Greater Than",!(NotANumber || Z || N)); - case 0x13: - CONDRET("Greater Than or Equal",Z || !(NotANumber || N)); - case 0x14: - CONDRET("Less Than",N && !(NotANumber || Z)); - case 0x15: - CONDRET("Less Than or Equal",Z || (N && !NotANumber)); - case 0x16: - CONDRET("Greater or Less Than",!(NotANumber || Z)); - case 0x17: - CONDRET("Greater, Less or Equal",!NotANumber); - case 0x18: - CONDRET("Not Greater, Less or Equal",NotANumber); - case 0x19: - CONDRET("Not Greater or Less Than",NotANumber || Z); - case 0x1a: - CONDRET("Not Less Than or Equal",NotANumber || !(N || Z)); - case 0x1b: - CONDRET("Not Less Than",NotANumber || Z || !N); - case 0x1c: - // CONDRET("Not Greater Than or Equal",NotANumber || (Z && N)); - CONDRET("Not Greater Than or Equal",!Z && (NotANumber || N)); - case 0x1d: - CONDRET("Not Greater Than",NotANumber || Z || N); - case 0x1e: - CONDRET("Signaling Not Equal",!Z); - case 0x1f: - CONDRET("Signaling True",1); + } + } + switch (size) { + case 0: + put_long (ad, (uae_s32) value); + break; + case 1: + put_long (ad, extract_single(value)); + break; + case 2: { + uae_u32 wrd1, wrd2, wrd3; + extract_extended(value, &wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + break; + } + case 3: { + uae_u32 wrd1, wrd2, wrd3; + extract_packed(value, &wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + break; + } + case 4: + put_word(ad, (uae_s16) value); + break; + case 5: { + uae_u32 wrd1, wrd2; + extract_double(value, &wrd1, &wrd2); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + break; + } + case 6: + put_byte(ad, (uae_s8) value); + break; default: - CONDRET("",-1); - } -#undef N -#undef Z -#undef I -#undef NotANumber + return 0; + } + return 1; } -void REGPARAM2 fdbcc_opp(uae_u32 opcode, uae_u16 extra) +PRIVATE inline int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) { - uaecptr pc = (uae_u32) m68k_getpc (); - uae_s32 disp = (uae_s32) (uae_s16) next_iword(); - int cc; + uae_u16 tmp; + uaecptr tmppc; + int mode; + int reg; - D(bug("fdbcc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + mode = (opcode >> 3) & 7; + reg = opcode & 7; + switch (mode) { + case 0: + case 1: + return 0; + case 2: + *ad = m68k_areg (regs, reg); + break; + case 3: + *ad = m68k_areg (regs, reg); + break; + case 4: + *ad = m68k_areg (regs, reg); + break; + case 5: + *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + break; + case 6: + *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch (reg) { + case 0: + *ad = (uae_s32) (uae_s16) next_iword(); + break; + case 1: + *ad = next_ilong(); + break; + case 2: + *ad = m68k_getpc (); + *ad += (uae_s32) (uae_s16) next_iword(); + break; + case 3: + tmppc = m68k_getpc (); + tmp = (uae_u16)next_iword(); + *ad = get_disp_ea_020 (tmppc, tmp); + break; + default: + return 0; + } + } + return 1; +} - cc = fpp_cond(opcode, extra & 0x3f); - if (cc == -1) { +#if FPU_DEBUG +# define CONDRET(s,x) fpu_debug(("fpp_cond %s = %d\n",s,(uint32)(x))); return (x) +#else +# define CONDRET(s,x) return (x) +#endif + +PRIVATE inline int FFPU fpp_cond(int condition) +{ +#if 1 +# define N ((FPU fpsr.condition_codes & NATIVE_FFLAG_NEGATIVE) == NATIVE_FFLAG_NEGATIVE) +# define Z ((FPU fpsr.condition_codes & NATIVE_FFLAG_ZERO) == NATIVE_FFLAG_ZERO) +# define I ((FPU fpsr.condition_codes & NATIVE_FFLAG_INFINITY) == NATIVE_FFLAG_INFINITY) +# define NaN ((FPU fpsr.condition_codes & NATIVE_FFLAG_NAN) == NATIVE_FFLAG_NAN) +#else +# define N ((FPU fpsr.condition_codes & NATIVE_FFLAG_NEGATIVE) != 0) +# define Z ((FPU fpsr.condition_codes & NATIVE_FFLAG_ZERO) != 0) +# define I ((FPU fpsr.condition_codes & NATIVE_FFLAG_INFINITY) != 0) +# define NaN ((FPU fpsr.condition_codes & NATIVE_FFLAG_NAN) != 0) +#endif + +#if 0 + return fpcctrue(condition); +#else + switch (condition) { + case 0x00: CONDRET("False",0); + case 0x01: CONDRET("Equal",Z); + case 0x02: CONDRET("Ordered Greater Than",!(NaN || Z || N)); + case 0x03: CONDRET("Ordered Greater Than or Equal",Z || !(NaN || N)); + case 0x04: CONDRET("Ordered Less Than",N && !(NaN || Z)); + case 0x05: CONDRET("Ordered Less Than or Equal",Z || (N && !NaN)); + case 0x06: CONDRET("Ordered Greater or Less Than",!(NaN || Z)); + case 0x07: CONDRET("Ordered",!NaN); + case 0x08: CONDRET("Unordered",NaN); + case 0x09: CONDRET("Unordered or Equal",NaN || Z); + case 0x0a: CONDRET("Unordered or Greater Than",NaN || !(N || Z)); + case 0x0b: CONDRET("Unordered or Greater or Equal",NaN || Z || !N); + case 0x0c: CONDRET("Unordered or Less Than",NaN || (N && !Z)); + case 0x0d: CONDRET("Unordered or Less or Equal",NaN || Z || N); + case 0x0e: CONDRET("Not Equal",!Z); + case 0x0f: CONDRET("True",1); + case 0x10: CONDRET("Signaling False",0); + case 0x11: CONDRET("Signaling Equal",Z); + case 0x12: CONDRET("Greater Than",!(NaN || Z || N)); + case 0x13: CONDRET("Greater Than or Equal",Z || !(NaN || N)); + case 0x14: CONDRET("Less Than",N && !(NaN || Z)); + case 0x15: CONDRET("Less Than or Equal",Z || (N && !NaN)); + case 0x16: CONDRET("Greater or Less Than",!(NaN || Z)); + case 0x17: CONDRET("Greater, Less or Equal",!NaN); + case 0x18: CONDRET("Not Greater, Less or Equal",NaN); + case 0x19: CONDRET("Not Greater or Less Than",NaN || Z); + case 0x1a: CONDRET("Not Less Than or Equal",NaN || !(N || Z)); + case 0x1b: CONDRET("Not Less Than",NaN || Z || !N); + case 0x1c: CONDRET("Not Greater Than or Equal", NaN || (N && !Z)); +// case 0x1c: CONDRET("Not Greater Than or Equal",!Z && (NaN || N)); + case 0x1d: CONDRET("Not Greater Than",NaN || Z || N); + case 0x1e: CONDRET("Signaling Not Equal",!Z); + case 0x1f: CONDRET("Signaling True",1); + default: CONDRET("",-1); + } +#endif + +# undef N +# undef Z +# undef I +# undef NaN +} + +void FFPU fpuop_dbcc(uae_u32 opcode, uae_u32 extra) +{ + fpu_debug(("fdbcc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + + uaecptr pc = (uae_u32) m68k_getpc (); + uae_s32 disp = (uae_s32) (uae_s16) next_iword(); + int cc = fpp_cond(extra & 0x3f); + if (cc == -1) { m68k_setpc (pc - 4); op_illg (opcode); - } else if (!cc) { + } else if (!cc) { int reg = opcode & 0x7; // this may have leaked. @@ -1213,1068 +1249,1103 @@ void REGPARAM2 fdbcc_opp(uae_u32 opcode, uae_u16 extra) m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & 0xffff0000) | (((m68k_dreg (regs, reg) & 0xffff) - 1) & 0xffff)); - + // condition reversed. // if ((m68k_dreg (regs, reg) & 0xffff) == 0xffff) if ((m68k_dreg (regs, reg) & 0xffff) != 0xffff) - m68k_setpc (pc + disp); - } + m68k_setpc (pc + disp); + } } -void REGPARAM2 fscc_opp(uae_u32 opcode, uae_u16 extra) +void FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) { - uae_u32 ad; - int cc; - - D(bug("fscc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); - - cc = fpp_cond(opcode, extra & 0x3f); - if (cc == -1) { + fpu_debug(("fscc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + + uae_u32 ad; + int cc = fpp_cond(extra & 0x3f); + if (cc == -1) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - } else if ((opcode & 0x38) == 0) { + } + else if ((opcode & 0x38) == 0) { m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) | - (cc ? 0xff : 0x00); - } else { - if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - } else - put_byte(ad, cc ? 0xff : 0x00); - } + (cc ? 0xff : 0x00); + } + else if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + } + else + put_byte(ad, cc ? 0xff : 0x00); } -void REGPARAM2 ftrapcc_opp(uae_u32 opcode, uaecptr oldpc) +void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) { - int cc; - - D(bug("ftrapcc_opp %X at %08lx\r\n", (uae_u32)opcode, m68k_getpc ())); - - cc = fpp_cond(opcode, opcode & 0x3f); - if (cc == -1) { + fpu_debug(("ftrapcc_opp %X at %08lx\n", (uae_u32)opcode, m68k_getpc ())); + + int cc = fpp_cond(opcode & 0x3f); + if (cc == -1) { m68k_setpc (oldpc); op_illg (opcode); - } - if (cc) + } + if (cc) Exception(7, oldpc - 2); } // NOTE that we get here also when there is a FNOP (nontrapping false, displ 0) -void REGPARAM2 fbcc_opp(uae_u32 opcode, uaecptr pc, uae_u32 extra) +void FFPU fpuop_bcc(uae_u32 opcode, uaecptr pc, uae_u32 extra) { - int cc; + fpu_debug(("fbcc_opp %X, %X at %08lx, jumpto=%X\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc (), extra )); - D(bug("fbcc_opp %X, %X at %08lx, jumpto=%X\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc (), extra )); - - cc = fpp_cond(opcode, opcode & 0x3f); - if (cc == -1) { + int cc = fpp_cond(opcode & 0x3f); + if (cc == -1) { m68k_setpc (pc); op_illg (opcode); - } else if (cc) { + } + else if (cc) { if ((opcode & 0x40) == 0) - extra = (uae_s32) (uae_s16) extra; + extra = (uae_s32) (uae_s16) extra; m68k_setpc (pc + extra); - } + } } // FSAVE has no post-increment // 0x1f180000 == IDLE state frame, coprocessor version number 1F -void REGPARAM2 fsave_opp(uae_u32 opcode) +void FFPU fpuop_save(uae_u32 opcode) { - uae_u32 ad; - int incr = (opcode & 0x38) == 0x20 ? -1 : 1; - int i; + fpu_debug(("fsave_opp at %08lx\n", m68k_getpc ())); - D(bug("fsave_opp at %08lx\r\n", m68k_getpc ())); + uae_u32 ad; + int incr = (opcode & 0x38) == 0x20 ? -1 : 1; + int i; - if (get_fp_ad(opcode, &ad) == 0) { + if (get_fp_ad(opcode, &ad) == 0) { m68k_setpc (m68k_getpc () - 2); op_illg (opcode); return; - } - + } + if (CPUType == 4) { // Put 4 byte 68040 IDLE frame. if (incr < 0) { ad -= 4; put_long (ad, 0x41000000); - } else { + } + else { put_long (ad, 0x41000000); ad += 4; } } else { // Put 28 byte 68881 IDLE frame. - if (incr < 0) { - D(bug("fsave_opp pre-decrement\r\n")); + if (incr < 0) { + fpu_debug(("fsave_opp pre-decrement\n")); ad -= 4; // What's this? Some BIU flags, or (incorrectly placed) command/condition? put_long (ad, 0x70000000); for (i = 0; i < 5; i++) { - ad -= 4; - put_long (ad, 0x00000000); + ad -= 4; + put_long (ad, 0x00000000); } ad -= 4; put_long (ad, 0x1f180000); // IDLE, vers 1f - } else { + } + else { put_long (ad, 0x1f180000); // IDLE, vers 1f ad += 4; for (i = 0; i < 5; i++) { - put_long (ad, 0x00000000); - ad += 4; + put_long (ad, 0x00000000); + ad += 4; } // What's this? Some BIU flags, or (incorrectly placed) command/condition? put_long (ad, 0x70000000); ad += 4; - } + } } - if ((opcode & 0x38) == 0x18) { + if ((opcode & 0x38) == 0x18) { m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 - D(bug("PROBLEM: fsave_opp post-increment\r\n")); + fpu_debug(("PROBLEM: fsave_opp post-increment\n")); } - if ((opcode & 0x38) == 0x20) { + if ((opcode & 0x38) == 0x20) { m68k_areg (regs, opcode & 7) = ad; - D(bug("fsave_opp pre-decrement %X -> A%d\r\n",ad,opcode & 7)); + fpu_debug(("fsave_opp pre-decrement %X -> A%d\n",ad,opcode & 7)); } } // FRESTORE has no pre-decrement -void REGPARAM2 frestore_opp(uae_u32 opcode) +void FFPU fpuop_restore(uae_u32 opcode) { - uae_u32 ad; - uae_u32 d; - int incr = (opcode & 0x38) == 0x20 ? -1 : 1; + fpu_debug(("frestore_opp at %08lx\n", m68k_getpc ())); - D(bug("frestore_opp at %08lx\r\n", m68k_getpc ())); + uae_u32 ad; + uae_u32 d; + int incr = (opcode & 0x38) == 0x20 ? -1 : 1; - if (get_fp_ad(opcode, &ad) == 0) { + if (get_fp_ad(opcode, &ad) == 0) { m68k_setpc (m68k_getpc () - 2); op_illg (opcode); return; - } + } if (CPUType == 4) { // 68040 if (incr < 0) { - D(bug("PROBLEM: frestore_opp incr < 0\r\n")); + fpu_debug(("PROBLEM: frestore_opp incr < 0\n")); // this may be wrong, but it's never called. ad -= 4; d = get_long (ad); if ((d & 0xff000000) != 0) { // Not a NULL frame? if ((d & 0x00ff0000) == 0) { // IDLE - D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4)); - } else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP - D(bug("PROBLEM: frestore_opp found UNIMP frame at %X\r\n",ad-4)); + fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); + } + else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP + fpu_debug(("PROBLEM: frestore_opp found UNIMP frame at %X\n",ad-4)); ad -= 44; - } else if ((d & 0x00ff0000) == 0x00600000) { // BUSY - D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4)); + } + else if ((d & 0x00ff0000) == 0x00600000) { // BUSY + fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); ad -= 92; } } - } else { + } + else { d = get_long (ad); - D(bug("frestore_opp frame at %X = %X\r\n",ad,d)); + fpu_debug(("frestore_opp frame at %X = %X\n",ad,d)); ad += 4; if ((d & 0xff000000) != 0) { // Not a NULL frame? if ((d & 0x00ff0000) == 0) { // IDLE - D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4)); - } else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP - D(bug("PROBLEM: frestore_opp found UNIMP frame at %X\r\n",ad-4)); + fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); + } + else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP + fpu_debug(("PROBLEM: frestore_opp found UNIMP frame at %X\n",ad-4)); ad += 44; - } else if ((d & 0x00ff0000) == 0x00600000) { // BUSY - D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4)); + } + else if ((d & 0x00ff0000) == 0x00600000) { // BUSY + fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); ad += 92; } } } - } else { + } + else { // 68881 - if (incr < 0) { - D(bug("PROBLEM: frestore_opp incr < 0\r\n")); + if (incr < 0) { + fpu_debug(("PROBLEM: frestore_opp incr < 0\n")); // this may be wrong, but it's never called. ad -= 4; d = get_long (ad); if ((d & 0xff000000) != 0) { - if ((d & 0x00ff0000) == 0x00180000) + if ((d & 0x00ff0000) == 0x00180000) ad -= 6 * 4; - else if ((d & 0x00ff0000) == 0x00380000) + else if ((d & 0x00ff0000) == 0x00380000) ad -= 14 * 4; - else if ((d & 0x00ff0000) == 0x00b40000) + else if ((d & 0x00ff0000) == 0x00b40000) ad -= 45 * 4; } - } else { + } + else { d = get_long (ad); - D(bug("frestore_opp frame at %X = %X\r\n",ad,d)); + fpu_debug(("frestore_opp frame at %X = %X\n",ad,d)); ad += 4; if ((d & 0xff000000) != 0) { // Not a NULL frame? - if ((d & 0x00ff0000) == 0x00180000) { // IDLE - D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4)); + if ((d & 0x00ff0000) == 0x00180000) { // IDLE + fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); ad += 6 * 4; - } else if ((d & 0x00ff0000) == 0x00380000) {// UNIMP? shouldn't it be 3C? + } + else if ((d & 0x00ff0000) == 0x00380000) {// UNIMP? shouldn't it be 3C? ad += 14 * 4; - D(bug("PROBLEM: frestore_opp found UNIMP? frame at %X\r\n",ad-4)); - } else if ((d & 0x00ff0000) == 0x00b40000) {// BUSY - D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4)); + fpu_debug(("PROBLEM: frestore_opp found UNIMP? frame at %X\n",ad-4)); + } + else if ((d & 0x00ff0000) == 0x00b40000) {// BUSY + fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); ad += 45 * 4; } } } - } - if ((opcode & 0x38) == 0x18) { - m68k_areg (regs, opcode & 7) = ad; - D(bug("frestore_opp post-increment %X -> A%d\r\n",ad,opcode & 7)); } - if ((opcode & 0x38) == 0x20) { + if ((opcode & 0x38) == 0x18) { + m68k_areg (regs, opcode & 7) = ad; + fpu_debug(("frestore_opp post-increment %X -> A%d\n",ad,opcode & 7)); + } + if ((opcode & 0x38) == 0x20) { m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 - D(bug("PROBLEM: frestore_opp pre-decrement\r\n")); + fpu_debug(("PROBLEM: frestore_opp pre-decrement\n")); } } -void fpp_opp(uae_u32 opcode, uae_u16 extra) +void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) { - int reg; - double src; + int reg; + fpu_register src; - D(bug("FPP %04lx %04x at %08lx\r\n", opcode & 0xffff, extra & 0xffff, - m68k_getpc () - 4)); + fpu_debug(("FPP %04lx %04x at %08lx\n", opcode & 0xffff, extra & 0xffff, + m68k_getpc () - 4)); - dump_fp_regs( "START"); + dump_registers( "START"); - switch ((extra >> 13) & 0x7) { - case 3: - D(bug("FMOVE -> \r\n")); - if (put_fp_value (regs.fp[(extra >> 7) & 7], opcode, extra) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - } - dump_fp_regs( "END "); - return; - case 4: - case 5: - if ((opcode & 0x38) == 0) { - if (extra & 0x2000) { // dr bit - if (extra & 0x1000) { - // according to the manual, the msb bits are always zero. - m68k_dreg (regs, opcode & 7) = regs.fpcr & 0xFFFF; - D(bug("FMOVEM regs.fpcr (%X) -> D%d\r\n", regs.fpcr, opcode & 7)); - } - if (extra & 0x0800) { - m68k_dreg (regs, opcode & 7) = regs.fpsr; - D(bug("FMOVEM regs.fpsr (%X) -> D%d\r\n", regs.fpsr, opcode & 7)); - } - if (extra & 0x0400) { - m68k_dreg (regs, opcode & 7) = regs.fpiar; - D(bug("FMOVEM regs.fpiar (%X) -> D%d\r\n", regs.fpiar, opcode & 7)); - } - } else { - if (extra & 0x1000) { - regs.fpcr = m68k_dreg (regs, opcode & 7); - D(bug("FMOVEM D%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr)); - } - if (extra & 0x0800) { - regs.fpsr = m68k_dreg (regs, opcode & 7); - D(bug("FMOVEM D%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr)); - } - if (extra & 0x0400) { - regs.fpiar = m68k_dreg (regs, opcode & 7); - D(bug("FMOVEM D%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar)); - } - } - // } else if ((opcode & 0x38) == 1) { - } else if ((opcode & 0x38) == 8) { - if (extra & 0x2000) { // dr bit - if (extra & 0x1000) { - // according to the manual, the msb bits are always zero. - m68k_areg (regs, opcode & 7) = regs.fpcr & 0xFFFF; - D(bug("FMOVEM regs.fpcr (%X) -> A%d\r\n", regs.fpcr, opcode & 7)); - } - if (extra & 0x0800) { - m68k_areg (regs, opcode & 7) = regs.fpsr; - D(bug("FMOVEM regs.fpsr (%X) -> A%d\r\n", regs.fpsr, opcode & 7)); - } - if (extra & 0x0400) { - m68k_areg (regs, opcode & 7) = regs.fpiar; - D(bug("FMOVEM regs.fpiar (%X) -> A%d\r\n", regs.fpiar, opcode & 7)); - } - } else { - if (extra & 0x1000) { - regs.fpcr = m68k_areg (regs, opcode & 7); - D(bug("FMOVEM A%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr)); - } - if (extra & 0x0800) { - regs.fpsr = m68k_areg (regs, opcode & 7); - D(bug("FMOVEM A%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr)); - } - if (extra & 0x0400) { - regs.fpiar = m68k_areg (regs, opcode & 7); - D(bug("FMOVEM A%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar)); - } - } - } else if ((opcode & 0x3f) == 0x3c) { - if ((extra & 0x2000) == 0) { - if (extra & 0x1000) { - regs.fpcr = next_ilong(); - D(bug("FMOVEM #<%X> -> regs.fpcr\r\n", regs.fpcr)); - } - if (extra & 0x0800) { - regs.fpsr = next_ilong(); - D(bug("FMOVEM #<%X> -> regs.fpsr\r\n", regs.fpsr)); - } - if (extra & 0x0400) { - regs.fpiar = next_ilong(); - D(bug("FMOVEM #<%X> -> regs.fpiar\r\n", regs.fpiar)); - } - } - } else if (extra & 0x2000) { - /* FMOVEM FPP->memory */ - - uae_u32 ad; - int incr = 0; - - if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_fp_regs( "END "); - return; - } - if ((opcode & 0x38) == 0x20) { - if (extra & 0x1000) - incr += 4; - if (extra & 0x0800) - incr += 4; - if (extra & 0x0400) - incr += 4; - } - ad -= incr; + switch ((extra >> 13) & 0x7) { + case 3: + fpu_debug(("FMOVE -> \n")); + if (put_fp_value (opcode, extra, FPU registers[(extra >> 7) & 7]) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + } + dump_registers( "END "); + return; + case 4: + case 5: + if ((opcode & 0x38) == 0) { + if (extra & 0x2000) { // dr bit if (extra & 0x1000) { // according to the manual, the msb bits are always zero. - put_long (ad, regs.fpcr & 0xFFFF); - D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad )); - ad += 4; + m68k_dreg (regs, opcode & 7) = get_fpcr() & 0xFFFF; + fpu_debug(("FMOVEM FPU fpcr (%X) -> D%d\n", get_fpcr(), opcode & 7)); } if (extra & 0x0800) { - put_long (ad, regs.fpsr); - D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad )); - ad += 4; + m68k_dreg (regs, opcode & 7) = get_fpsr(); + fpu_debug(("FMOVEM FPU fpsr (%X) -> D%d\n", get_fpsr(), opcode & 7)); } if (extra & 0x0400) { - put_long (ad, regs.fpiar); - D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad )); - ad += 4; + m68k_dreg (regs, opcode & 7) = FPU instruction_address; + fpu_debug(("FMOVEM FPU instruction_address (%X) -> D%d\n", FPU instruction_address, opcode & 7)); } - ad -= incr; - if ((opcode & 0x38) == 0x18) // post-increment? - m68k_areg (regs, opcode & 7) = ad; - if ((opcode & 0x38) == 0x20) // pre-decrement? - m68k_areg (regs, opcode & 7) = ad; - } else { - /* FMOVEM memory->FPP */ - - uae_u32 ad; - - if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_fp_regs( "END "); - return; - } - - // ad = (opcode & 0x38) == 0x20 ? ad - 12 : ad; - int incr = 0; - if((opcode & 0x38) == 0x20) { - if (extra & 0x1000) - incr += 4; - if (extra & 0x0800) - incr += 4; - if (extra & 0x0400) - incr += 4; - ad = ad - incr; - } - + } + else { if (extra & 0x1000) { - regs.fpcr = get_long (ad); - D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr )); - ad += 4; + set_fpcr( m68k_dreg (regs, opcode & 7) ); + fpu_debug(("FMOVEM D%d (%X) -> FPU fpcr\n", opcode & 7, get_fpcr())); } if (extra & 0x0800) { - regs.fpsr = get_long (ad); - D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad, regs.fpsr )); - ad += 4; + set_fpsr( m68k_dreg (regs, opcode & 7) ); + fpu_debug(("FMOVEM D%d (%X) -> FPU fpsr\n", opcode & 7, get_fpsr())); } if (extra & 0x0400) { - regs.fpiar = get_long (ad); - D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad, regs.fpiar )); - ad += 4; + FPU instruction_address = m68k_dreg (regs, opcode & 7); + fpu_debug(("FMOVEM D%d (%X) -> FPU instruction_address\n", opcode & 7, FPU instruction_address)); } - if ((opcode & 0x38) == 0x18) // post-increment? - m68k_areg (regs, opcode & 7) = ad; - if ((opcode & 0x38) == 0x20) // pre-decrement? - // m68k_areg (regs, opcode & 7) = ad - 12; - m68k_areg (regs, opcode & 7) = ad - incr; } - dump_fp_regs( "END "); - return; - case 6: - case 7: - { - uae_u32 ad, list = 0; - int incr = 0; - if (extra & 0x2000) { - /* FMOVEM FPP->memory */ - - D(bug("FMOVEM FPP->memory\r\n")); - - if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_fp_regs( "END "); - return; - } - switch ((extra >> 11) & 3) { - case 0: /* static pred */ - list = extra & 0xff; - incr = -1; - break; - case 1: /* dynamic pred */ - list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - incr = -1; - break; - case 2: /* static postinc */ - list = extra & 0xff; - incr = 1; - break; - case 3: /* dynamic postinc */ - list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - incr = 1; - break; - } - - if (incr < 0) { - for(reg=7; reg>=0; reg--) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - from_exten(regs.fp[reg],&wrd1, &wrd2, &wrd3); - ad -= 4; - put_long (ad, wrd3); - ad -= 4; - put_long (ad, wrd2); - ad -= 4; - put_long (ad, wrd1); - } - list <<= 1; - } - } else { - for(reg=0; reg<8; reg++) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - from_exten(regs.fp[reg],&wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); - ad += 4; - } - list <<= 1; - } - } - - if ((opcode & 0x38) == 0x18) // post-increment? - m68k_areg (regs, opcode & 7) = ad; - if ((opcode & 0x38) == 0x20) // pre-decrement? - m68k_areg (regs, opcode & 7) = ad; - } else { - /* FMOVEM memory->FPP */ - - D(bug("FMOVEM memory->FPP\r\n")); - - if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_fp_regs( "END "); - return; - } - switch ((extra >> 11) & 3) { - case 0: /* static pred */ - D(bug("memory->FMOVEM FPP not legal mode.\r\n")); - list = extra & 0xff; - incr = -1; - break; - case 1: /* dynamic pred */ - D(bug("memory->FMOVEM FPP not legal mode.\r\n")); - list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - incr = -1; - break; - case 2: /* static postinc */ - list = extra & 0xff; - incr = 1; - break; - case 3: /* dynamic postinc */ - list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - incr = 1; - break; - } - - /**/ - if (incr < 0) { - // not reached - for(reg=7; reg>=0; reg--) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - ad -= 4; - wrd3 = get_long (ad); - ad -= 4; - wrd2 = get_long (ad); - ad -= 4; - wrd1 = get_long (ad); - // regs.fp[reg] = to_exten (wrd1, wrd2, wrd3); - to_exten_no_normalize (wrd1, wrd2, wrd3, (uae_u32 *)®s.fp[reg]); - } - list <<= 1; - } - } else { - for(reg=0; reg<8; reg++) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - ad += 4; - wrd3 = get_long (ad); - ad += 4; - // regs.fp[reg] = to_exten (wrd1, wrd2, wrd3); - to_exten_no_normalize (wrd1, wrd2, wrd3, (uae_u32 *)®s.fp[reg]); - } - list <<= 1; - } - } - if ((opcode & 0x38) == 0x18) // post-increment? - m68k_areg (regs, opcode & 7) = ad; - if ((opcode & 0x38) == 0x20) // pre-decrement? - m68k_areg (regs, opcode & 7) = ad; - } - } - dump_fp_regs( "END "); - return; - case 0: - case 2: - reg = (extra >> 7) & 7; - if ((extra & 0xfc00) == 0x5c00) { - D(bug("FMOVECR memory->FPP\r\n")); - switch (extra & 0x7f) { - case 0x00: - // regs.fp[reg] = 4.0 * atan(1.0); - regs.fp[reg] = 3.1415926535897932384626433832795; - D(bug("FP const: Pi\r\n")); - break; - case 0x0b: - // regs.fp[reg] = log10 (2.0); - regs.fp[reg] = 0.30102999566398119521373889472449; - D(bug("FP const: Log 10 (2)\r\n")); - break; - case 0x0c: - // regs.fp[reg] = exp (1.0); - regs.fp[reg] = 2.7182818284590452353602874713527; - D(bug("FP const: e\r\n")); - break; - case 0x0d: - // regs.fp[reg] = log (exp (1.0)) / log (2.0); - regs.fp[reg] = 1.4426950408889634073599246810019; - D(bug("FP const: Log 2 (e)\r\n")); - break; - case 0x0e: - // regs.fp[reg] = log (exp (1.0)) / log (10.0); - regs.fp[reg] = 0.43429448190325182765112891891661; - D(bug("FP const: Log 10 (e)\r\n")); - break; - case 0x0f: - regs.fp[reg] = 0.0; - D(bug("FP const: zero\r\n")); - break; - case 0x30: - // regs.fp[reg] = log (2.0); - regs.fp[reg] = 0.69314718055994530941723212145818; - D(bug("FP const: ln(2)\r\n")); - break; - case 0x31: - // regs.fp[reg] = log (10.0); - regs.fp[reg] = 2.3025850929940456840179914546844; - D(bug("FP const: ln(10)\r\n")); - break; - case 0x32: - // ?? - regs.fp[reg] = 1.0e0; - D(bug("FP const: 1.0e0\r\n")); - break; - case 0x33: - regs.fp[reg] = 1.0e1; - D(bug("FP const: 1.0e1\r\n")); - break; - case 0x34: - regs.fp[reg] = 1.0e2; - D(bug("FP const: 1.0e2\r\n")); - break; - case 0x35: - regs.fp[reg] = 1.0e4; - D(bug("FP const: 1.0e4\r\n")); - break; - case 0x36: - regs.fp[reg] = 1.0e8; - D(bug("FP const: 1.0e8\r\n")); - break; - case 0x37: - regs.fp[reg] = 1.0e16; - D(bug("FP const: 1.0e16\r\n")); - break; - case 0x38: - regs.fp[reg] = 1.0e32; - D(bug("FP const: 1.0e32\r\n")); - break; - case 0x39: - regs.fp[reg] = 1.0e64; - D(bug("FP const: 1.0e64\r\n")); - break; - case 0x3a: - regs.fp[reg] = 1.0e128; - D(bug("FP const: 1.0e128\r\n")); - break; - case 0x3b: - regs.fp[reg] = 1.0e256; - D(bug("FP const: 1.0e256\r\n")); - break; - - // Valid for 64 bits only (see fpu.cpp) -#if 0 - case 0x3c: - regs.fp[reg] = 1.0e512; - D(bug("FP const: 1.0e512\r\n")); - break; - case 0x3d: - regs.fp[reg] = 1.0e1024; - D(bug("FP const: 1.0e1024\r\n")); - break; - case 0x3e: - regs.fp[reg] = 1.0e2048; - D(bug("FP const: 1.0e2048\r\n")); - break; - case 0x3f: - regs.fp[reg] = 1.0e4096; - D(bug("FP const: 1.0e4096\r\n")); - break; -#endif - default: - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - break; - } - // these *do* affect the status reg - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - dump_fp_regs( "END "); - return; - } - if (get_fp_value (opcode, extra, &src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_fp_regs( "END "); - return; - } - D(bug("returned from get_fp_value m68k_getpc()=%X\r\n",m68k_getpc())); - - switch (extra & 0x7f) { - case 0x00: /* FMOVE */ - D(bug("FMOVE %.04f\r\n",(float)src)); - regs.fp[reg] = src; - // -> reg DOES affect the status reg - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x01: /* FINT */ - D(bug("FINT %.04f\r\n",(float)src)); - // regs.fp[reg] = (int) (src + 0.5); - switch(regs.fpcr & 0x30) { - case ROUND_TO_ZERO: - regs.fp[reg] = round_to_zero(src); - break; - case ROUND_TO_NEGATIVE_INFINITY: - regs.fp[reg] = floor(src); - break; - case ROUND_TO_NEAREST: - regs.fp[reg] = round_to_nearest(src); - break; - case ROUND_TO_POSITIVE_INFINITY: - regs.fp[reg] = ceil(src); - break; - } - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x02: /* FSINH */ - D(bug("FSINH %.04f\r\n",(float)src)); - regs.fp[reg] = sinh (src); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x03: /* FINTRZ */ - D(bug("FINTRZ %.04f\r\n",(float)src)); - // regs.fp[reg] = (int) src; - regs.fp[reg] = round_to_zero(src); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x04: /* FSQRT */ - D(bug("FSQRT %.04f\r\n",(float)src)); - regs.fp[reg] = sqrt (src); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x06: /* FLOGNP1 */ - D(bug("FLOGNP1 %.04f\r\n",(float)src)); - regs.fp[reg] = log (src + 1.0); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x08: /* FETOXM1 */ - D(bug("FETOXM1 %.04f\r\n",(float)src)); - regs.fp[reg] = exp (src) - 1.0; - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x09: /* FTANH */ - D(bug("FTANH %.04f\r\n",(float)src)); - regs.fp[reg] = tanh (src); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x0a: /* FATAN */ - D(bug("FATAN %.04f\r\n",(float)src)); - regs.fp[reg] = atan (src); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x0c: /* FASIN */ - D(bug("FASIN %.04f\r\n",(float)src)); - regs.fp[reg] = asin (src); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x0d: /* FATANH */ - D(bug("FATANH %.04f\r\n",(float)src)); -#if 1 /* The BeBox doesn't have atanh, and it isn't in the HPUX libm either */ - regs.fp[reg] = log ((1 + src) / (1 - src)) / 2; -#else - regs.fp[reg] = atanh (src); -#endif - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x0e: /* FSIN */ - D(bug("FSIN %.04f\r\n",(float)src)); - regs.fp[reg] = sin (src); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x0f: /* FTAN */ - D(bug("FTAN %.04f\r\n",(float)src)); - regs.fp[reg] = tan (src); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x10: /* FETOX */ - D(bug("FETOX %.04f\r\n",(float)src)); - regs.fp[reg] = exp (src); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x11: /* FTWOTOX */ - D(bug("FTWOTOX %.04f\r\n",(float)src)); - regs.fp[reg] = pow(2.0, src); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x12: /* FTENTOX */ - D(bug("FTENTOX %.04f\r\n",(float)src)); - regs.fp[reg] = pow(10.0, src); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x14: /* FLOGN */ - D(bug("FLOGN %.04f\r\n",(float)src)); - regs.fp[reg] = log (src); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x15: /* FLOG10 */ - D(bug("FLOG10 %.04f\r\n",(float)src)); - regs.fp[reg] = log10 (src); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x16: /* FLOG2 */ - D(bug("FLOG2 %.04f\r\n",(float)src)); - regs.fp[reg] = log (src) / log (2.0); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x18: /* FABS */ - case 0x58: /* single precision rounding */ - case 0x5C: /* double precision rounding */ - D(bug("FABS %.04f\r\n",(float)src)); - regs.fp[reg] = src < 0 ? -src : src; - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x19: /* FCOSH */ - D(bug("FCOSH %.04f\r\n",(float)src)); - regs.fp[reg] = cosh(src); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x1a: /* FNEG */ - D(bug("FNEG %.04f\r\n",(float)src)); - regs.fp[reg] = -src; - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x1c: /* FACOS */ - D(bug("FACOS %.04f\r\n",(float)src)); - regs.fp[reg] = acos(src); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x1d: /* FCOS */ - D(bug("FCOS %.04f\r\n",(float)src)); - regs.fp[reg] = cos(src); - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x1e: /* FGETEXP */ - D(bug("FGETEXP %.04f\r\n",(float)src)); -#if HAVE_IEEE_DOUBLE - if( IS_INFINITY((uae_u32 *)&src) ) { - MAKE_NAN( (uae_u32 *)®s.fp[reg] ); - } else { - regs.fp[reg] = FAST_FGETEXP( (uae_u32 *)&src ); - } -#else - if(src == 0) { - regs.fp[reg] = (double)0; - } else { - int expon; - frexp (src, &expon); - regs.fp[reg] = (double) (expon - 1); - } -#endif - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x1f: /* FGETMAN */ - D(bug("FGETMAN %.04f\r\n",(float)src)); -#if HAVE_IEEE_DOUBLE - if( src == 0 ) { - regs.fp[reg] = 0; - } else if( IS_INFINITY((uae_u32 *)&src) ) { - MAKE_NAN( (uae_u32 *)®s.fp[reg] ); - } else { - regs.fp[reg] = src; - FAST_REMOVE_EXPONENT( (uae_u32 *)®s.fp[reg] ); - } -#else - { - int expon; - regs.fp[reg] = frexp (src, &expon) * 2.0; - } -#endif - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x20: /* FDIV */ - D(bug("FDIV %.04f\r\n",(float)src)); - regs.fp[reg] /= src; - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x21: /* FMOD */ - D(bug("FMOD %.04f\r\n",(float)src)); - // regs.fp[reg] = regs.fp[reg] - (double) ((int) (regs.fp[reg] / src)) * src; - { double quot = round_to_zero(regs.fp[reg] / src); -#if HAVE_IEEE_DOUBLE - uae_u32 sign = GET_QUOTIENT_SIGN((uae_u32 *)®s.fp[reg],(uae_u32 *)&src); -#endif - regs.fp[reg] = regs.fp[reg] - quot * src; - MAKE_FPSR(regs.fpsr,regs.fp[reg]); -#if HAVE_IEEE_DOUBLE - regs.fpsr = MAKE_QUOTIENT(regs.fpsr,quot,sign); -#endif - } - break; - case 0x22: /* FADD */ - case 0x62: /* single */ - case 0x66: /* double */ - D(bug("FADD %.04f\r\n",(float)src)); - regs.fp[reg] += src; - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x23: /* FMUL */ - D(bug("FMUL %.04f\r\n",(float)src)); -#if HAVE_IEEE_DOUBLE - GET_DEST_FLAGS((uae_u32 *)®s.fp[reg]); - GET_SOURCE_FLAGS((uae_u32 *)&src); - if(fl_dest.in_range && fl_source.in_range) { - regs.fp[reg] *= src; - } else if( fl_dest.nan || fl_source.nan || - fl_dest.zero && fl_source.infinity || - fl_dest.infinity && fl_source.zero ) - { - MAKE_NAN( (uae_u32 *)®s.fp[reg] ); - } else if( fl_dest.zero || fl_source.zero ) { - if( fl_dest.negative && !fl_source.negative || - !fl_dest.negative && fl_source.negative) - { - MAKE_ZERO_NEGATIVE((uae_u32 *)®s.fp[reg]); - } else { - MAKE_ZERO_POSITIVE((uae_u32 *)®s.fp[reg]); - } - } else { - if( fl_dest.negative && !fl_source.negative || - !fl_dest.negative && fl_source.negative) - { - MAKE_INF_NEGATIVE((uae_u32 *)®s.fp[reg]); - } else { - MAKE_INF_POSITIVE((uae_u32 *)®s.fp[reg]); - } - } -#else - D(bug("FMUL %.04f\r\n",(float)src)); - regs.fp[reg] *= src; -#endif - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x24: /* FSGLDIV */ - D(bug("FSGLDIV %.04f\r\n",(float)src)); - // TODO: round to float. - regs.fp[reg] /= src; - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x25: /* FREM */ - D(bug("FREM %.04f\r\n",(float)src)); - // regs.fp[reg] = regs.fp[reg] - (double) ((int) (regs.fp[reg] / src + 0.5)) * src; - { double quot = round_to_nearest(regs.fp[reg] / src); -#if HAVE_IEEE_DOUBLE - uae_u32 sign = GET_QUOTIENT_SIGN((uae_u32 *)®s.fp[reg],(uae_u32 *)&src); -#endif - regs.fp[reg] = regs.fp[reg] - quot * src; - MAKE_FPSR(regs.fpsr,regs.fp[reg]); -#if HAVE_IEEE_DOUBLE - regs.fpsr = MAKE_QUOTIENT(regs.fpsr,quot,sign); -#endif - } - break; - - case 0x26: /* FSCALE */ - D(bug("FSCALE %.04f\r\n",(float)src)); - - // TODO: - // Overflow, underflow - -#if HAVE_IEEE_DOUBLE - if( IS_INFINITY((uae_u32 *)®s.fp[reg]) ) { - MAKE_NAN( (uae_u32 *)®s.fp[reg] ); - } else { - // When the absolute value of the source operand is >= 2^14, - // an overflow or underflow always results. - // Here (int) cast is okay. - FAST_SCALE( (uae_u32 *)®s.fp[reg], (int)round_to_zero(src) ); - } -#else - if(src != 0) { // Manual says: src==0 -> FPn - regs.fp[reg] *= exp (log (2.0) * src); - } -#endif - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x27: /* FSGLMUL */ - D(bug("FSGLMUL %.04f\r\n",(float)src)); - regs.fp[reg] *= src; - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x28: /* FSUB */ - D(bug("FSUB %.04f\r\n",(float)src)); - regs.fp[reg] -= src; - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x30: /* FSINCOS */ - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - D(bug("FSINCOS %.04f\r\n",(float)src)); - // Cosine must be calculated first if same register - regs.fp[extra & 7] = cos(src); - regs.fp[reg] = sin (src); - // Set fpsr according to the sine result - MAKE_FPSR(regs.fpsr,regs.fp[reg]); - break; - case 0x38: /* FCMP */ - D(bug("FCMP %.04f\r\n",(float)src)); - - // The infinity bit is always cleared by the FCMP - // instruction since it is not used by any of the - // conditional predicate equations. - -#if HAVE_IEEE_DOUBLE - if( IS_INFINITY((uae_u32 *)&src) ) { - if( IS_NEGATIVE((uae_u32 *)&src) ) { - // negative infinity - if( IS_INFINITY((uae_u32 *)®s.fp[reg]) && IS_NEGATIVE((uae_u32 *)®s.fp[reg]) ) { - // Zero, Negative - regs.fpsr = (regs.fpsr & 0x00FFFFFF) | 0x4000000 | 0x8000000; - D(bug("-INF cmp -INF -> NZ\r\n")); - } else { - // None - regs.fpsr = (regs.fpsr & 0x00FFFFFF); - D(bug("x cmp -INF -> None\r\n")); - } - } else { - // positive infinity - if( IS_INFINITY((uae_u32 *)®s.fp[reg]) && !IS_NEGATIVE((uae_u32 *)®s.fp[reg]) ) { - // Zero - regs.fpsr = (regs.fpsr & 0x00FFFFFF) | 0x4000000; - D(bug("+INF cmp +INF -> Z\r\n")); - } else { - // Negative - regs.fpsr = (regs.fpsr & 0x00FFFFFF) | 0x8000000; - D(bug("X cmp +INF -> N\r\n")); - } - } - } else { - double tmp = regs.fp[reg] - src; - // regs.fpsr = (regs.fpsr & 0x00FFFFFF) | (tmp == 0 ? 0x4000000 : 0) | (tmp < 0 ? 0x8000000 : 0); - regs.fpsr = (tmp == 0 ? 0x4000000 : 0) | (tmp < 0 ? 0x8000000 : 0); - } -#else - { - double tmp = regs.fp[reg] - src; - MAKE_FPSR(regs.fpsr,tmp); - } -#endif - break; - case 0x3a: /* FTST */ - D(bug("FTST %.04f\r\n",(float)src)); - // MAKE_FPSR(regs.fpsr,regs.fp[reg]); - MAKE_FPSR(regs.fpsr,src); - break; - default: - D(bug("ILLEGAL F OP %X\r\n",opcode)); - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - break; +// } else if ((opcode & 0x38) == 1) { } - D(bug("END m68k_getpc()=%X\r\n",m68k_getpc())); - dump_fp_regs( "END "); + else if ((opcode & 0x38) == 8) { + if (extra & 0x2000) { // dr bit + if (extra & 0x1000) { + // according to the manual, the msb bits are always zero. + m68k_areg (regs, opcode & 7) = get_fpcr() & 0xFFFF; + fpu_debug(("FMOVEM FPU fpcr (%X) -> A%d\n", get_fpcr(), opcode & 7)); + } + if (extra & 0x0800) { + m68k_areg (regs, opcode & 7) = get_fpsr(); + fpu_debug(("FMOVEM FPU fpsr (%X) -> A%d\n", get_fpsr(), opcode & 7)); + } + if (extra & 0x0400) { + m68k_areg (regs, opcode & 7) = FPU instruction_address; + fpu_debug(("FMOVEM FPU instruction_address (%X) -> A%d\n", FPU instruction_address, opcode & 7)); + } + } else { + if (extra & 0x1000) { + set_fpcr( m68k_areg (regs, opcode & 7) ); + fpu_debug(("FMOVEM A%d (%X) -> FPU fpcr\n", opcode & 7, get_fpcr())); + } + if (extra & 0x0800) { + set_fpsr( m68k_areg (regs, opcode & 7) ); + fpu_debug(("FMOVEM A%d (%X) -> FPU fpsr\n", opcode & 7, get_fpsr())); + } + if (extra & 0x0400) { + FPU instruction_address = m68k_areg (regs, opcode & 7); + fpu_debug(("FMOVEM A%d (%X) -> FPU instruction_address\n", opcode & 7, FPU instruction_address)); + } + } + } + else if ((opcode & 0x3f) == 0x3c) { + if ((extra & 0x2000) == 0) { + if (extra & 0x1000) { + set_fpcr( next_ilong() ); + fpu_debug(("FMOVEM #<%X> -> FPU fpcr\n", get_fpcr())); + } + if (extra & 0x0800) { + set_fpsr( next_ilong() ); + fpu_debug(("FMOVEM #<%X> -> FPU fpsr\n", get_fpsr())); + } + if (extra & 0x0400) { + FPU instruction_address = next_ilong(); + fpu_debug(("FMOVEM #<%X> -> FPU instruction_address\n", FPU instruction_address)); + } + } + } + else if (extra & 0x2000) { + /* FMOVEM FPP->memory */ + uae_u32 ad; + int incr = 0; + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + if ((opcode & 0x38) == 0x20) { + if (extra & 0x1000) + incr += 4; + if (extra & 0x0800) + incr += 4; + if (extra & 0x0400) + incr += 4; + } + ad -= incr; + if (extra & 0x1000) { + // according to the manual, the msb bits are always zero. + put_long (ad, get_fpcr() & 0xFFFF); + fpu_debug(("FMOVEM FPU fpcr (%X) -> mem %X\n", get_fpcr(), ad )); + ad += 4; + } + if (extra & 0x0800) { + put_long (ad, get_fpsr()); + fpu_debug(("FMOVEM FPU fpsr (%X) -> mem %X\n", get_fpsr(), ad )); + ad += 4; + } + if (extra & 0x0400) { + put_long (ad, FPU instruction_address); + fpu_debug(("FMOVEM FPU instruction_address (%X) -> mem %X\n", FPU instruction_address, ad )); + ad += 4; + } + ad -= incr; + if ((opcode & 0x38) == 0x18) // post-increment? + m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) // pre-decrement? + m68k_areg (regs, opcode & 7) = ad; + } + else { + /* FMOVEM memory->FPP */ + uae_u32 ad; + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + + // ad = (opcode & 0x38) == 0x20 ? ad - 12 : ad; + int incr = 0; + if((opcode & 0x38) == 0x20) { + if (extra & 0x1000) + incr += 4; + if (extra & 0x0800) + incr += 4; + if (extra & 0x0400) + incr += 4; + ad = ad - incr; + } + + if (extra & 0x1000) { + set_fpcr( get_long (ad) ); + fpu_debug(("FMOVEM mem %X (%X) -> FPU fpcr\n", ad, get_fpcr() )); + ad += 4; + } + if (extra & 0x0800) { + set_fpsr( get_long (ad) ); + fpu_debug(("FMOVEM mem %X (%X) -> FPU fpsr\n", ad, get_fpsr() )); + ad += 4; + } + if (extra & 0x0400) { + FPU instruction_address = get_long (ad); + fpu_debug(("FMOVEM mem %X (%X) -> FPU instruction_address\n", ad, FPU instruction_address )); + ad += 4; + } + if ((opcode & 0x38) == 0x18) // post-increment? + m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) // pre-decrement? +// m68k_areg (regs, opcode & 7) = ad - 12; + m68k_areg (regs, opcode & 7) = ad - incr; + } + dump_registers( "END "); return; - } - D(bug("ILLEGAL F OP 2 %X\r\n",opcode)); - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_fp_regs( "END "); + case 6: + case 7: { + uae_u32 ad, list = 0; + int incr = 0; + if (extra & 0x2000) { + /* FMOVEM FPP->memory */ + fpu_debug(("FMOVEM FPP->memory\n")); + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + switch ((extra >> 11) & 3) { + case 0: /* static pred */ + list = extra & 0xff; + incr = -1; + break; + case 1: /* dynamic pred */ + list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + incr = -1; + break; + case 2: /* static postinc */ + list = extra & 0xff; + incr = 1; + break; + case 3: /* dynamic postinc */ + list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + incr = 1; + break; + } + + if (incr < 0) { + for(reg=7; reg>=0; reg--) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + extract_extended(FPU registers[reg],&wrd1, &wrd2, &wrd3); + ad -= 4; + put_long (ad, wrd3); + ad -= 4; + put_long (ad, wrd2); + ad -= 4; + put_long (ad, wrd1); + } + list <<= 1; + } + } + else { + for(reg=0; reg<8; reg++) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + extract_extended(FPU registers[reg],&wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + ad += 4; + } + list <<= 1; + } + } + if ((opcode & 0x38) == 0x18) // post-increment? + m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) // pre-decrement? + m68k_areg (regs, opcode & 7) = ad; + } + else { + /* FMOVEM memory->FPP */ + fpu_debug(("FMOVEM memory->FPP\n")); + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + switch ((extra >> 11) & 3) { + case 0: /* static pred */ + fpu_debug(("memory->FMOVEM FPP not legal mode.\n")); + list = extra & 0xff; + incr = -1; + break; + case 1: /* dynamic pred */ + fpu_debug(("memory->FMOVEM FPP not legal mode.\n")); + list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + incr = -1; + break; + case 2: /* static postinc */ + list = extra & 0xff; + incr = 1; + break; + case 3: /* dynamic postinc */ + list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + incr = 1; + break; + } + + /**/ + if (incr < 0) { + // not reached + for(reg=7; reg>=0; reg--) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + ad -= 4; + wrd3 = get_long (ad); + ad -= 4; + wrd2 = get_long (ad); + ad -= 4; + wrd1 = get_long (ad); + // FPU registers[reg] = make_extended(wrd1, wrd2, wrd3); + make_extended_no_normalize (wrd1, wrd2, wrd3, FPU registers[reg]); + } + list <<= 1; + } + } + else { + for(reg=0; reg<8; reg++) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + ad += 4; + // FPU registers[reg] = make_extended(wrd1, wrd2, wrd3); + make_extended_no_normalize (wrd1, wrd2, wrd3, FPU registers[reg]); + } + list <<= 1; + } + } + if ((opcode & 0x38) == 0x18) // post-increment? + m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) // pre-decrement? + m68k_areg (regs, opcode & 7) = ad; + } + dump_registers( "END "); + return; + } + case 0: + case 2: + reg = (extra >> 7) & 7; + if ((extra & 0xfc00) == 0x5c00) { + fpu_debug(("FMOVECR memory->FPP\n")); + switch (extra & 0x7f) { + case 0x00: + // FPU registers[reg] = 4.0 * atan(1.0); + FPU registers[reg] = 3.1415926535897932384626433832795; + fpu_debug(("FP const: Pi\n")); + break; + case 0x0b: + // FPU registers[reg] = log10 (2.0); + FPU registers[reg] = 0.30102999566398119521373889472449; + fpu_debug(("FP const: Log 10 (2)\n")); + break; + case 0x0c: + // FPU registers[reg] = exp (1.0); + FPU registers[reg] = 2.7182818284590452353602874713527; + fpu_debug(("FP const: e\n")); + break; + case 0x0d: + // FPU registers[reg] = log (exp (1.0)) / log (2.0); + FPU registers[reg] = 1.4426950408889634073599246810019; + fpu_debug(("FP const: Log 2 (e)\n")); + break; + case 0x0e: + // FPU registers[reg] = log (exp (1.0)) / log (10.0); + FPU registers[reg] = 0.43429448190325182765112891891661; + fpu_debug(("FP const: Log 10 (e)\n")); + break; + case 0x0f: + FPU registers[reg] = 0.0; + fpu_debug(("FP const: zero\n")); + break; + case 0x30: + // FPU registers[reg] = log (2.0); + FPU registers[reg] = 0.69314718055994530941723212145818; + fpu_debug(("FP const: ln(2)\n")); + break; + case 0x31: + // FPU registers[reg] = log (10.0); + FPU registers[reg] = 2.3025850929940456840179914546844; + fpu_debug(("FP const: ln(10)\n")); + break; + case 0x32: + // ?? + FPU registers[reg] = 1.0e0; + fpu_debug(("FP const: 1.0e0\n")); + break; + case 0x33: + FPU registers[reg] = 1.0e1; + fpu_debug(("FP const: 1.0e1\n")); + break; + case 0x34: + FPU registers[reg] = 1.0e2; + fpu_debug(("FP const: 1.0e2\n")); + break; + case 0x35: + FPU registers[reg] = 1.0e4; + fpu_debug(("FP const: 1.0e4\n")); + break; + case 0x36: + FPU registers[reg] = 1.0e8; + fpu_debug(("FP const: 1.0e8\n")); + break; + case 0x37: + FPU registers[reg] = 1.0e16; + fpu_debug(("FP const: 1.0e16\n")); + break; + case 0x38: + FPU registers[reg] = 1.0e32; + fpu_debug(("FP const: 1.0e32\n")); + break; + case 0x39: + FPU registers[reg] = 1.0e64; + fpu_debug(("FP const: 1.0e64\n")); + break; + case 0x3a: + FPU registers[reg] = 1.0e128; + fpu_debug(("FP const: 1.0e128\n")); + break; + case 0x3b: + FPU registers[reg] = 1.0e256; + fpu_debug(("FP const: 1.0e256\n")); + break; + + // Valid for 64 bits only (see fpu.cpp) +#if 0 + case 0x3c: + FPU registers[reg] = 1.0e512; + fpu_debug(("FP const: 1.0e512\n")); + break; + case 0x3d: + FPU registers[reg] = 1.0e1024; + fpu_debug(("FP const: 1.0e1024\n")); + break; + case 0x3e: + FPU registers[reg] = 1.0e2048; + fpu_debug(("FP const: 1.0e2048\n")); + break; + case 0x3f: + FPU registers[reg] = 1.0e4096; + fpu_debug(("FP const: 1.0e4096\n")); + break; +#endif + default: + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + break; + } + // these *do* affect the status reg + make_fpsr(FPU registers[reg]); + dump_registers( "END "); + return; + } + + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + fpu_debug(("returned from get_fp_value m68k_getpc()=%X\n",m68k_getpc())); + + switch (extra & 0x7f) { + case 0x00: /* FMOVE */ + fpu_debug(("FMOVE %.04f\n",(double)src)); + FPU registers[reg] = src; + // -> reg DOES affect the status reg + make_fpsr(FPU registers[reg]); + break; + case 0x01: /* FINT */ + fpu_debug(("FINT %.04f\n",(double)src)); + // FPU registers[reg] = (int) (src + 0.5); + // FIXME: use native rounding mode flags + switch (get_fpcr() & 0x30) { + case FPCR_ROUND_ZERO: + FPU registers[reg] = round_to_zero(src); + break; + case FPCR_ROUND_MINF: + FPU registers[reg] = floor(src); + break; + case FPCR_ROUND_NEAR: + FPU registers[reg] = round_to_nearest(src); + break; + case FPCR_ROUND_PINF: + FPU registers[reg] = ceil(src); + break; + } + make_fpsr(FPU registers[reg]); + break; + case 0x02: /* FSINH */ + fpu_debug(("FSINH %.04f\n",(double)src)); + FPU registers[reg] = sinh (src); + make_fpsr(FPU registers[reg]); + break; + case 0x03: /* FINTRZ */ + fpu_debug(("FINTRZ %.04f\n",(double)src)); + // FPU registers[reg] = (int) src; + FPU registers[reg] = round_to_zero(src); + make_fpsr(FPU registers[reg]); + break; + case 0x04: /* FSQRT */ + fpu_debug(("FSQRT %.04f\n",(double)src)); + FPU registers[reg] = sqrt (src); + make_fpsr(FPU registers[reg]); + break; + case 0x06: /* FLOGNP1 */ + fpu_debug(("FLOGNP1 %.04f\n",(double)src)); + FPU registers[reg] = log (src + 1.0); + make_fpsr(FPU registers[reg]); + break; + case 0x08: /* FETOXM1 */ + fpu_debug(("FETOXM1 %.04f\n",(double)src)); + FPU registers[reg] = exp (src) - 1.0; + make_fpsr(FPU registers[reg]); + break; + case 0x09: /* FTANH */ + fpu_debug(("FTANH %.04f\n",(double)src)); + FPU registers[reg] = tanh (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0a: /* FATAN */ + fpu_debug(("FATAN %.04f\n",(double)src)); + FPU registers[reg] = atan (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0c: /* FASIN */ + fpu_debug(("FASIN %.04f\n",(double)src)); + FPU registers[reg] = asin (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0d: /* FATANH */ + fpu_debug(("FATANH %.04f\n",(double)src)); +#if HAVE_ATANH + FPU registers[reg] = atanh (src); +#else + /* The BeBox doesn't have atanh, and it isn't in the HPUX libm either */ + FPU registers[reg] = log ((1 + src) / (1 - src)) / 2; +#endif + make_fpsr(FPU registers[reg]); + break; + case 0x0e: /* FSIN */ + fpu_debug(("FSIN %.04f\n",(double)src)); + FPU registers[reg] = sin (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0f: /* FTAN */ + fpu_debug(("FTAN %.04f\n",(double)src)); + FPU registers[reg] = tan (src); + make_fpsr(FPU registers[reg]); + break; + case 0x10: /* FETOX */ + fpu_debug(("FETOX %.04f\n",(double)src)); + FPU registers[reg] = exp (src); + make_fpsr(FPU registers[reg]); + break; + case 0x11: /* FTWOTOX */ + fpu_debug(("FTWOTOX %.04f\n",(double)src)); + FPU registers[reg] = pow(2.0, src); + make_fpsr(FPU registers[reg]); + break; + case 0x12: /* FTENTOX */ + fpu_debug(("FTENTOX %.04f\n",(double)src)); + FPU registers[reg] = pow(10.0, src); + make_fpsr(FPU registers[reg]); + break; + case 0x14: /* FLOGN */ + fpu_debug(("FLOGN %.04f\n",(double)src)); + FPU registers[reg] = log (src); + make_fpsr(FPU registers[reg]); + break; + case 0x15: /* FLOG10 */ + fpu_debug(("FLOG10 %.04f\n",(double)src)); + FPU registers[reg] = log10 (src); + make_fpsr(FPU registers[reg]); + break; + case 0x16: /* FLOG2 */ + fpu_debug(("FLOG2 %.04f\n",(double)src)); + FPU registers[reg] = log (src) / log (2.0); + make_fpsr(FPU registers[reg]); + break; + case 0x18: /* FABS */ + case 0x58: /* single precision rounding */ + case 0x5C: /* double precision rounding */ + fpu_debug(("FABS %.04f\n",(double)src)); + FPU registers[reg] = src < 0 ? -src : src; + make_fpsr(FPU registers[reg]); + break; + case 0x19: /* FCOSH */ + fpu_debug(("FCOSH %.04f\n",(double)src)); + FPU registers[reg] = cosh(src); + make_fpsr(FPU registers[reg]); + break; + case 0x1a: /* FNEG */ + fpu_debug(("FNEG %.04f\n",(double)src)); + FPU registers[reg] = -src; + make_fpsr(FPU registers[reg]); + break; + case 0x1c: /* FACOS */ + fpu_debug(("FACOS %.04f\n",(double)src)); + FPU registers[reg] = acos(src); + make_fpsr(FPU registers[reg]); + break; + case 0x1d: /* FCOS */ + fpu_debug(("FCOS %.04f\n",(double)src)); + FPU registers[reg] = cos(src); + make_fpsr(FPU registers[reg]); + break; + case 0x1e: /* FGETEXP */ + fpu_debug(("FGETEXP %.04f\n",(double)src)); +#if FPU_HAVE_IEEE_DOUBLE + if( isinf(src) ) { + make_nan( FPU registers[reg] ); + } + else { + FPU registers[reg] = fast_fgetexp( src ); + } +#else + if(src == 0) { + FPU registers[reg] = (fpu_register)0; + } + else { + int expon; + frexp (src, &expon); + FPU registers[reg] = (fpu_register) (expon - 1); + } +#endif + make_fpsr(FPU registers[reg]); + break; + case 0x1f: /* FGETMAN */ + fpu_debug(("FGETMAN %.04f\n",(double)src)); +#if FPU_HAVE_IEEE_DOUBLE + if( src == 0 ) { + FPU registers[reg] = 0; + } + else if( isinf(src) ) { + make_nan( FPU registers[reg] ); + } + else { + FPU registers[reg] = src; + fast_remove_exponent( FPU registers[reg] ); + } +#else + { + int expon; + FPU registers[reg] = frexp (src, &expon) * 2.0; + } +#endif + make_fpsr(FPU registers[reg]); + break; + case 0x20: /* FDIV */ + fpu_debug(("FDIV %.04f\n",(double)src)); + FPU registers[reg] /= src; + make_fpsr(FPU registers[reg]); + break; + case 0x21: /* FMOD */ + fpu_debug(("FMOD %.04f\n",(double)src)); + // FPU registers[reg] = FPU registers[reg] - (fpu_register) ((int) (FPU registers[reg] / src)) * src; + { + fpu_register quot = round_to_zero(FPU registers[reg] / src); +#if FPU_HAVE_IEEE_DOUBLE + uae_u32 sign = get_quotient_sign(FPU registers[reg],src); +#endif + FPU registers[reg] = FPU registers[reg] - quot * src; + make_fpsr(FPU registers[reg]); +#if FPU_HAVE_IEEE_DOUBLE + make_quotient(quot, sign); +#endif + } + break; + case 0x22: /* FADD */ + case 0x62: /* single */ + case 0x66: /* double */ + fpu_debug(("FADD %.04f\n",(double)src)); + FPU registers[reg] += src; + make_fpsr(FPU registers[reg]); + break; + case 0x23: /* FMUL */ + fpu_debug(("FMUL %.04f\n",(double)src)); +#if FPU_HAVE_IEEE_DOUBLE + get_dest_flags(FPU registers[reg]); + get_source_flags(src); + if(fl_dest.in_range && fl_source.in_range) { + FPU registers[reg] *= src; + } + else if (fl_dest.nan || fl_source.nan || + fl_dest.zero && fl_source.infinity || + fl_dest.infinity && fl_source.zero ) { + make_nan( FPU registers[reg] ); + } + else if (fl_dest.zero || fl_source.zero ) { + if (fl_dest.negative && !fl_source.negative || + !fl_dest.negative && fl_source.negative) { + make_zero_negative(FPU registers[reg]); + } + else { + make_zero_positive(FPU registers[reg]); + } + } + else { + if( fl_dest.negative && !fl_source.negative || + !fl_dest.negative && fl_source.negative) { + make_inf_negative(FPU registers[reg]); + } + else { + make_inf_positive(FPU registers[reg]); + } + } +#else + fpu_debug(("FMUL %.04f\n",(double)src)); + FPU registers[reg] *= src; +#endif + make_fpsr(FPU registers[reg]); + break; + case 0x24: /* FSGLDIV */ + fpu_debug(("FSGLDIV %.04f\n",(double)src)); + // TODO: round to float. + FPU registers[reg] /= src; + make_fpsr(FPU registers[reg]); + break; + case 0x25: /* FREM */ + fpu_debug(("FREM %.04f\n",(double)src)); + // FPU registers[reg] = FPU registers[reg] - (double) ((int) (FPU registers[reg] / src + 0.5)) * src; + { + fpu_register quot = round_to_nearest(FPU registers[reg] / src); +#if FPU_HAVE_IEEE_DOUBLE + uae_u32 sign = get_quotient_sign(FPU registers[reg],src); +#endif + FPU registers[reg] = FPU registers[reg] - quot * src; + make_fpsr(FPU registers[reg]); +#if FPU_HAVE_IEEE_DOUBLE + make_quotient(quot,sign); +#endif + } + break; + + case 0x26: /* FSCALE */ + fpu_debug(("FSCALE %.04f\n",(double)src)); + + // TODO: + // Overflow, underflow + +#if FPU_HAVE_IEEE_DOUBLE + if( isinf(FPU registers[reg]) ) { + make_nan( FPU registers[reg] ); + } + else { + // When the absolute value of the source operand is >= 2^14, + // an overflow or underflow always results. + // Here (int) cast is okay. + fast_scale( FPU registers[reg], (int)round_to_zero(src) ); + } +#else + if (src != 0) { // Manual says: src==0 -> FPn + FPU registers[reg] *= exp (log (2.0) * src); + } +#endif + make_fpsr(FPU registers[reg]); + break; + case 0x27: /* FSGLMUL */ + fpu_debug(("FSGLMUL %.04f\n",(double)src)); + FPU registers[reg] *= src; + make_fpsr(FPU registers[reg]); + break; + case 0x28: /* FSUB */ + fpu_debug(("FSUB %.04f\n",(double)src)); + FPU registers[reg] -= src; + make_fpsr(FPU registers[reg]); + break; + case 0x30: /* FSINCOS */ + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + fpu_debug(("FSINCOS %.04f\n",(double)src)); + // Cosine must be calculated first if same register + FPU registers[extra & 7] = cos(src); + FPU registers[reg] = sin (src); + // Set FPU fpsr according to the sine result + make_fpsr(FPU registers[reg]); + break; + case 0x38: /* FCMP */ + fpu_debug(("FCMP %.04f\n",(double)src)); + + // The infinity bit is always cleared by the FCMP + // instruction since it is not used by any of the + // conditional predicate equations. + +#if FPU_HAVE_IEEE_DOUBLE + if( isinf(src) ) { + if( isneg(src) ) { + // negative infinity + if( isinf(FPU registers[reg]) && isneg(FPU registers[reg]) ) { + // Zero, Negative + FPU fpsr.condition_codes = NATIVE_FFLAG_ZERO | NATIVE_FFLAG_NEGATIVE; + fpu_debug(("-INF cmp -INF -> NZ\n")); + } + else { + // None + FPU fpsr.condition_codes = 0; + fpu_debug(("x cmp -INF -> None\n")); + } + } + else { + // positive infinity + if( isinf(FPU registers[reg]) && !isneg(FPU registers[reg]) ) { + // Zero + FPU fpsr.condition_codes = NATIVE_FFLAG_ZERO; + fpu_debug(("+INF cmp +INF -> Z\n")); + } + else { + // Negative + FPU fpsr.condition_codes = NATIVE_FFLAG_NEGATIVE; + fpu_debug(("X cmp +INF -> N\n")); + } + } + } + else { + fpu_register tmp = FPU registers[reg] - src; + FPU fpsr.condition_codes + = (iszero(tmp) ? NATIVE_FFLAG_ZERO : 0) + | (isneg(tmp) ? NATIVE_FFLAG_NEGATIVE : 0) + ; + } +#else + { + fpu_register tmp = FPU registers[reg] - src; + make_fpsr(tmp); + } +#endif + break; + case 0x3a: /* FTST */ + fpu_debug(("FTST %.04f\n",(double)src)); + // make_fpsr(FPU registers[reg]); + make_fpsr(src); + break; + default: + fpu_debug(("ILLEGAL F OP %X\n",opcode)); + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + break; + } + fpu_debug(("END m68k_getpc()=%X\n",m68k_getpc())); + dump_registers( "END "); + return; + } + + fpu_debug(("ILLEGAL F OP 2 %X\n",opcode)); + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); } /* -------------------------- Initialization -------------------------- */ -void fpu_set_integral_fpu (bool is_integral) +void FFPU fpu_init (bool integral_68040) { - D(bug("fpu_set_integral_fpu : %s\n", (is_integral ? "yes" : "no"))); + fpu_debug(("fpu_init\n")); + + static bool initialized_lookup_tables = false; + if (!initialized_lookup_tables) { + fpu_init_native_fflags(); + fpu_init_native_exceptions(); + fpu_init_native_accrued_exceptions(); + initialized_lookup_tables = true; + } + + FPU is_integral = integral_68040; + set_fpcr(0); + set_fpsr(0); + FPU instruction_address = 0; } -void fpu_init (void) +void FFPU fpu_exit (void) { - D(bug("fpu_init\n")); - regs.fpcr = regs.fpsr = regs.fpiar = 0; + fpu_debug(("fpu_exit\n")); } -void fpu_exit (void) +void FFPU fpu_reset (void) { - D(bug("fpu_exit\n")); -} - -void fpu_reset (void) -{ - D(bug("fpu_reset\n")); + fpu_debug(("fpu_reset\n")); fpu_exit(); - fpu_init(); + fpu_init(FPU is_integral); } diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_uae.h b/BasiliskII/src/uae_cpu/fpu/fpu_uae.h new file mode 100644 index 00000000..76648713 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/fpu_uae.h @@ -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 */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp index 83afdf84..7ce9421c 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp +++ b/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp @@ -1,7 +1,7 @@ /* * fpu_x86.cpp - 68881/68040 fpu code for x86/Windows an Linux/x86. * - * Basilisk II (C) 1997-2001 Christian Bauer + * Basilisk II (C) 1997-1999 Christian Bauer * * MC68881/68040 fpu emulation * @@ -26,7 +26,6 @@ * * Interface * Almost the same as original. Please see the comments in "fpu.h". - * Call fpu_init() and fpu_set_integral_fpu() before cpu thread starts up. * * * Why assembly? @@ -38,48 +37,56 @@ * * regs.piar is not updated. * - * regs.fpcr always contains the real 68881/68040 control word. + * regs.FPU fpcr always contains the real 68881/68040 control word. * - * regs.fpsr is not kept up-to-date, for efficiency reasons. - * Most of the FPU commands update this in a way or another, - * but it is not read nearly that often. Therefore, three host-specific - * words hold the status byte and exception byte ("sw"), accrued exception - * byte ("sw_accrued") and the quotient byte ("sw_quotient"), as explained below. + * regs.FPU fpsr is not kept up-to-date, for efficiency reasons. + * Most of the FPU commands update this in a way or another, but it is not + * read nearly that often. Therefore, three host-specific words hold the + * status byte and exception byte ("x86_status_word"), accrued exception + * byte ("x86_status_word_accrued") and the quotient byte ("FPU fpsr.quotient"), + * as explained below. * * CONDITION CODE - QUOTIENT - EXCEPTION STATUS - ACCRUED EXCEPTION * CONDITION CODE (N,Z,I,NAN) - * updated after each opcode, if needed. - * x86 assembly opcodes call FXAM and store the status word to "sw". - * When regs.fpsr is actually used, the value of "sw" is translated. + * - updated after each opcode, if needed. + * - x86 assembly opcodes call FXAM and store the status word to + * "x86_status_word". + * - When regs.FPU fpsr is actually used, the value of "x86_status_word" + * is translated. * QUOTIENT BYTE - * Updated by frem, fmod, frestore(null frame) - * Stored in "sw_quotient" in correct bit position, combined when - * regs.fpsr is actually used. + * - Updated by frem, fmod, frestore(null frame) + * - Stored in "FPU fpsr.quotient" in correct bit position, combined when + * regs.FPU fpsr is actually used. * EXCEPTION STATUS (BSUN,SNAN,OPERR,OVFL,UNFL,DZ,INEX2,INEX1) - * updated after each opcode, if needed. - * Saved in x86 form in "sw". - * When regs.fpsr is actually used, the value of "sw" is translated. - * Only fcc_op can set BSUN + * - updated after each opcode, if needed. + * - Saved in x86 form in "x86_status_word". + * - When regs.FPU fpsr is actually used, the value of "x86_status_word" + * is translated. + * - Only fcc_op can set BSUN * ACCRUED EXCEPTION (ACCR_IOP,ACCR_OVFL,ACCR_UNFL,ACCR_DZ,ACCR_INEX) - * updated after each opcode, if needed. - * Logically OR'ed in x86 form to "sw_accrued". - * When regs.fpsr is actually used, the value of "sw_accrued" is translated. + * - updated after each opcode, if needed. + * - Logically OR'ed in x86 form to "x86_status_word_accrued". + * - When regs.FPU fpsr is actually used, the value of + * "x86_status_word_accrued" is translated. * - * When "sw" and "sw_accrued" are stored, all pending x86 FPU - * exceptions are cleared, if there are any. + * When "x86_status_word" and "x86_status_word_accrued" are stored, + * all pending x86 FPU exceptions are cleared, if there are any. * - * Writing to "regs.fpsr" reverse-maps to x86 status/exception values - * and stores the values in "sw", "sw_accrued" and "sw_quotient". + * Writing to "regs.FPU fpsr" reverse-maps to x86 status/exception values and + * stores the values in "x86_status_word", "x86_status_word_accrued" + * and "FPU fpsr.quotient". * - * So, "sw" and "sw_accrued" are not in correct bit positions - * and have x86 values, but "sw_quotient" is at correct position. + * So, "x86_status_word" and "x86_status_word_accrued" are not in + * correct bit positions and have x86 values, but "FPU fpsr.quotient" is at + * correct position. * * Note that it does not matter that the reverse-mapping is not exact - * (both SW_IE and SW_DE are mapped to ACCR_IOP, but ACCR_IOP maps to SW_IE - * only), the MacOS always sees the correct exception bits. + * (both SW_IE and SW_DE are mapped to ACCR_IOP, but ACCR_IOP maps to + * SW_IE only), the MacOS always sees the correct exception bits. * - * Also note the usage of the fake BSUN flag SW_FAKE_BSUN. If you change the - * x86 FPU code, you must make sure that you don't generate any FPU stack faults. + * Also note the usage of the fake BSUN flag SW_FAKE_BSUN. If you change + * the x86 FPU code, you must make sure that you don't generate any FPU + * stack faults. * * * x86 co-processor initialization: @@ -129,21 +136,54 @@ #include #include -#include +#include #include "sysdeps.h" #include "memory.h" #include "readcpu.h" #include "newcpu.h" +#define FPU_IMPLEMENTATION +#include "fpu/fpu.h" #include "fpu/fpu_x86.h" #include "fpu/fpu_x86_asm.h" +/* Global FPU context */ +fpu_t fpu; + +/* -------------------------------------------------------------------------- */ +/* --- Native Support --- */ +/* -------------------------------------------------------------------------- */ + +#include "fpu/flags.h" +#include "fpu/exceptions.h" +#include "fpu/rounding.h" +#include "fpu/impl.h" + +#include "fpu/flags.cpp" +#include "fpu/exceptions.cpp" +#include "fpu/rounding.cpp" + +/* -------------------------------------------------------------------------- */ +/* --- Scopes Definition --- */ +/* -------------------------------------------------------------------------- */ + +#undef PUBLIC +#define PUBLIC /**/ + +#undef PRIVATE +#define PRIVATE static + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + /* ---------------------------- Compatibility ---------------------------- */ #define BYTE uint8 #define WORD uint16 #define DWORD uint32 -#define _ASM __asm__ __volatile__ #define min(a, b) (((a) < (b)) ? (a) : (b)) /* ---------------------------- Configuration ---------------------------- */ @@ -161,48 +201,46 @@ consider checking the host exception flags after FISTP (search for /* gb-- I only tested the following configurations: USE_3_BIT_QUOTIENT 1 -- still changes to apply if no 3-bit quotient - DEBUG 1 or 0 + FPU_DEBUG 1 or 0 USE_CONSISTENCY_CHECKING 0 I3_ON_ILLEGAL_FPU_OP 0 -- and this won't change I3_ON_FTRAPCC 0 -- and this won't change */ #define USE_3_BIT_QUOTIENT 1 -#define DEBUG 0 +//#define FPU_DEBUG 0 -- now defined in "fpu/fpu.h" #define USE_CONSISTENCY_CHECKING 0 #define I3_ON_ILLEGAL_FPU_OP 0 #define I3_ON_FTRAPCC 0 - -/* ---------------------------- Registers ---------------------------- */ - -// "regs.fp" is not used. regs.fpcr, regs.fpsr and regs.fpiar are used. - -typedef BYTE *float80; -typedef BYTE float80_s[10]; -typedef BYTE float80_s_aligned[16]; - -static float80_s_aligned fp_reg[8]; - - /* ---------------------------- Debugging ---------------------------- */ -#if DEBUG -//#pragma optimize("",off) -#endif +PUBLIC void FFPU fpu_dump_registers(void) +{ + for (int i = 0; i < 8; i++){ + printf ("FP%d: %g ", i, fpu_get_register(i)); + if ((i & 3) == 3) + printf ("\n"); + } +} -// extern "C" {int debugging_fpp = 0;} +PUBLIC void FFPU fpu_dump_flags(void) +{ + printf ("N=%d Z=%d I=%d NAN=%d\n", + (get_fpsr() & FPSR_CCB_NEGATIVE) != 0, + (get_fpsr() & FPSR_CCB_ZERO)!= 0, + (get_fpsr() & FPSR_CCB_INFINITY) != 0, + (get_fpsr() & FPSR_CCB_NAN) != 0); +} #include "debug.h" -#if DEBUG +#if FPU_DEBUG #undef __inline__ #define __inline__ -//#undef D -//#define D(x) { if(debugging_fpp) { (x); } } -static void dump_first_bytes_buf( char *b, BYTE *buf, int32 actual ) +PRIVATE void FFPU dump_first_bytes_buf(char *b, uae_u8* buf, uae_s32 actual) { char bb[10]; int32 i, bytes = min(actual,100); @@ -215,16 +253,14 @@ static void dump_first_bytes_buf( char *b, BYTE *buf, int32 actual ) strcat((char*)b,"\r\n"); } -static void dump_first_bytes( BYTE *buf, int32 actual ) +PUBLIC void FFPU dump_first_bytes(uae_u8 * buf, uae_s32 actual) { char msg[256]; dump_first_bytes_buf( msg, buf, actual ); D(bug("%s\n", msg)); } -#define CONDRET(s,x) D(bug("fpp_cond %s = %d\r\n",s,(uint32)(x))); return (x) -static char * etos( float80 e ) REGPARAM; -static char * etos( float80 e ) +PRIVATE char * FFPU etos(fpu_register const & e) { static char _s[10][30]; static int _ix = 0; @@ -236,10 +272,11 @@ static char * etos( float80 e ) FSTP DWORD PTR f } */ - _ASM( "fldt %1\n" + __asm__ __volatile__( + "fldt %1\n" "fstp %0\n" : "=m" (f) - : "m" (*e) + : "m" (e) ); if(++_ix >= 10) _ix = 0; @@ -247,7 +284,8 @@ static char * etos( float80 e ) sprintf( _s[_ix], "%.04f", (float)f ); return( _s[_ix] ); } -static void dump_fp_regs( char *s ) + +PUBLIC void FFPU dump_registers(const char *s) { char b[512]; @@ -255,42 +293,47 @@ static void dump_fp_regs( char *s ) b, "%s: %s, %s, %s, %s, %s, %s, %s, %s\r\n", s, - etos(fp_reg[0]), - etos(fp_reg[1]), - etos(fp_reg[2]), - etos(fp_reg[3]), - etos(fp_reg[4]), - etos(fp_reg[5]), - etos(fp_reg[6]), - etos(fp_reg[7]) + etos(FPU registers[0]), + etos(FPU registers[1]), + etos(FPU registers[2]), + etos(FPU registers[3]), + etos(FPU registers[4]), + etos(FPU registers[5]), + etos(FPU registers[6]), + etos(FPU registers[7]) ); D(bug((char*)b)); } #else -#define CONDRET(s,x) return (x) -#define dump_fp_regs(s) {} + +PUBLIC void FFPU dump_registers(const char *) +{ +} + +PUBLIC void FFPU dump_first_bytes(uae_u8 *, uae_s32) +{ +} + #endif /* ---------------------------- FPU consistency ---------------------------- */ #if USE_CONSISTENCY_CHECKING -static uae_u16 checked_sw_atstart; - -static void FPU_CONSISTENCY_CHECK_START() +PRIVATE void FFPU FPU_CONSISTENCY_CHECK_START(void) { /* _asm { FNSTSW checked_sw_atstart } */ - _ASM("fnstsw %0" : "=m" (checked_sw_atstart)); + __asm__ __volatile__("fnstsw %0" : "=m" (checked_sw_atstart)); } -static void FPU_CONSISTENCY_CHECK_STOP(char *name) +PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *name) { uae_u16 checked_sw_atend; // _asm FNSTSW checked_sw_atend - _ASM("fnstsw %0" : "=m" (checked_sw_attend)); + __asm__ __volatile__("fnstsw %0" : "=m" (checked_sw_attend)); char msg[256]; // Check for FPU stack overflows/underflows. @@ -309,7 +352,7 @@ static void FPU_CONSISTENCY_CHECK_STOP(char *name) /* if(checked_sw_atstart != 0x400 || checked_sw_atend != 0x400) { wsprintf( - msg, "Op %s, sw before=%X, sw after=%X\r\n", + msg, "Op %s, x86_status_word before=%X, x86_status_word after=%X\r\n", name, (int)checked_sw_atstart, (int)checked_sw_atend ); OutputDebugString(msg); @@ -317,178 +360,52 @@ static void FPU_CONSISTENCY_CHECK_STOP(char *name) */ } #else -#define FPU_CONSISTENCY_CHECK_START() -#define FPU_CONSISTENCY_CHECK_STOP(name) +PRIVATE void FFPU FPU_CONSISTENCY_CHECK_START(void) +{ +} + +PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *) +{ +} #endif -/* ---------------------------- FPU type ---------------------------- */ - -static uae_u32 is_integral_68040_fpu = 0; - - /* ---------------------------- Status byte ---------------------------- */ -// 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) - // Map x86 FXAM codes -> m68k fpu status byte -#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) +#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) // Initial state after boot, reset and frestore(null frame) -#define SW_INITIAL SW_FINITE - -// These hold the contents of the fpsr, in Intel values. -static DWORD sw = SW_INITIAL; -static DWORD sw_accrued = 0; -static DWORD sw_quotient = 0; - - -/* ---------------------------- Control word ---------------------------- */ - -// Initial state after boot, reset and frestore(null frame) -#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) - -static WORD cw = CW_INITIAL; - - -/* ---------------------------- FMOVECR constants ---------------------------- */ - -static float80_s - // Suported by x86 FPU - const_pi, - const_lg2, - const_l2e, - const_z, - const_ln2, - const_1, - - // Not suported by x86 FPU - const_e, - const_log_10_e, - const_ln_10, - const_1e1, - const_1e2, - const_1e4, - const_1e8, - const_1e16, - const_1e32, - const_1e64, - const_1e128, - const_1e256, - const_1e512, - const_1e1024, - const_1e2048, - const_1e4096; - - -/* ---------------------------- Saved host FPU state ---------------------------- */ - -static BYTE m_fpu_state_original[108]; // 90/94/108 - - -/* ---------------------------- Map tables ---------------------------- */ - -typedef void REGPARAM2 fpuop_func( uae_u32, uae_u16 ); -extern "C" { fpuop_func *fpufunctbl[65536]; } - -// Control word -- need only one-way mapping -static const uae_u16 cw_rc_mac2host[] = { - CW_RC_NEAR, - CW_RC_ZERO, - CW_RC_DOWN, - CW_RC_UP -}; -static const uae_u16 cw_pc_mac2host[] = { - CW_PC_EXTENDED, - CW_PC_SINGLE, - CW_PC_DOUBLE, - CW_PC_RESERVED -}; - -// Status word -- need two-way mapping -static uae_u32 sw_cond_host2mac[ 0x48 ]; -static uae_u16 sw_cond_mac2host[ 16 ]; - -static uae_u32 exception_host2mac[ 0x80 ]; -static uae_u32 exception_mac2host[ 0x100 ]; - -static uae_u32 accrued_exception_host2mac[ 0x40 ]; -static uae_u32 accrued_exception_mac2host[ 0x20 ]; - - -/* ---------------------------- Control functions ---------------------------- */ - -/* - Exception enable byte is ignored, but the same value is returned - that was previously set. -*/ -static void __inline__ set_host_fpu_control_word() -{ - cw = (cw & ~(X86_ROUND_CONTROL_MASK|X86_PRECISION_CONTROL_MASK)) | - cw_rc_mac2host[ (regs.fpcr & ROUND_CONTROL_MASK) >> 4 ] | - cw_pc_mac2host[ (regs.fpcr & PRECISION_CONTROL_MASK) >> 6 ]; - - // Writing to control register is very slow (no register renaming on - // ppro++, and most of all, it's one of those serializing commands). -/* _asm { - FLDCW cw - } */ - _ASM("fldcw %0" : : "m" (cw)); -} +#define SW_INITIAL SW_FINITE /* ---------------------------- Status functions ---------------------------- */ -static void __inline__ SET_BSUN_ON_NAN() +PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN () { - if( (sw & (SW_Z_I_NAN_MASK)) == SW_NAN ) { - sw |= SW_FAKE_BSUN; - sw_accrued |= SW_IE; + if( (x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN ) { + x86_status_word |= SW_FAKE_BSUN; + x86_status_word_accrued |= SW_IE; } } -static void __inline__ build_ex_status() +PRIVATE void __inline__ FFPU build_ex_status () { - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw_accrued |= sw; + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; } } -static void __inline__ to_fpsr() -{ - regs.fpsr = - sw_cond_host2mac[ (sw & 0x4700) >> 8 ] | - sw_quotient | - exception_host2mac[ sw & (SW_FAKE_BSUN|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE) ] | - accrued_exception_host2mac[ sw_accrued & (SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE) ] - ; -} - -static void __inline__ from_fpsr() -{ - sw = - sw_cond_mac2host[ (regs.fpsr & 0x0F000000) >> 24 ] | - exception_mac2host[ (regs.fpsr & 0x0000FF00) >> 8 ]; - sw_quotient = regs.fpsr & 0x00FF0000; - sw_accrued = accrued_exception_mac2host[ (regs.fpsr & 0xF8) >> 3 ]; -} - - // TODO_BIGENDIAN; all of these. /* ---------------------------- Type functions ---------------------------- */ @@ -497,10 +414,11 @@ When the FPU creates a NAN, the NAN always contains the same bit pattern in the mantissa. All bits of the mantissa are ones for any precision. When the user creates a NAN, any nonzero bit pattern can be stored in the mantissa. */ -static __inline__ void MAKE_NAN(float80 p) +PRIVATE __inline__ void FFPU MAKE_NAN (fpu_register & f) { // Make it non-signaling. - memset( p, 0xFF, sizeof(float80_s)-1 ); + uae_u8 * p = (uae_u8 *) &f; + memset( p, 0xFF, sizeof(fpu_register) - 1 ); p[9] = 0x7F; } @@ -509,70 +427,73 @@ For single- and double-precision infinities the fraction is a zero. For extended-precision infinities, the mantissa’s MSB, the explicit integer bit, can be either one or zero. */ -static __inline__ uae_u32 IS_INFINITY(float80 p) +PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f) { + uae_u8 * p = (uae_u8 *) &f; if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) { - if( *((uae_u32 *)p) == 0 && - ( *((uae_u32 *)&p[4]) & 0x7FFFFFFF ) == 0 ) - { + if ((*((uae_u32 *)&p[0]) == 0) && + ((*((uae_u32 *)&p[4]) & 0x7FFFFFFF) == 0)) return(1); - } } return(0); } -static __inline__ uae_u32 IS_NAN(float80 p) +PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f) { + uae_u8 * p = (uae_u8 *) &f; if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) { - if( *((uae_u32 *)p) != 0 || - ( *((uae_u32 *)&p[4]) & 0x7FFFFFFF ) != 0 ) - { + if ((*((uae_u32 *)&p[0]) == 0) && + ((*((uae_u32 *)&p[4]) & 0x7FFFFFFF) != 0)) return(1); - } } return(0); } -static __inline__ uae_u32 IS_ZERO(float80 p) +PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f) { + uae_u8 * p = (uae_u8 *) &f; return *((uae_u32 *)p) == 0 && *((uae_u32 *)&p[4]) == 0 && ( *((uae_u16 *)&p[8]) & 0x7FFF ) == 0; } -static __inline__ void MAKE_INF_POSITIVE(float80 p) +PRIVATE __inline__ void FFPU MAKE_INF_POSITIVE (fpu_register & f) { - memset( p, 0, sizeof(float80_s)-2 ); + uae_u8 * p = (uae_u8 *) &f; + memset( p, 0, sizeof(fpu_register)-2 ); *((uae_u16 *)&p[8]) = 0x7FFF; } -static __inline__ void MAKE_INF_NEGATIVE(float80 p) +PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (fpu_register & f) { - memset( p, 0, sizeof(float80_s)-2 ); + uae_u8 * p = (uae_u8 *) &f; + memset( p, 0, sizeof(fpu_register)-2 ); *((uae_u16 *)&p[8]) = 0xFFFF; } -static __inline__ void MAKE_ZERO_POSITIVE(float80 p) +PRIVATE __inline__ void FFPU MAKE_ZERO_POSITIVE (fpu_register & f) { - memset( p, 0, sizeof(float80_s) ); + uae_u32 * const p = (uae_u32 *) &f; + memset( p, 0, sizeof(fpu_register) ); } -static __inline__ void MAKE_ZERO_NEGATIVE(float80 *p) +PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f) { - memset( p, 0, sizeof(float80_s) ); + uae_u32 * const p = (uae_u32 *) &f; + memset( p, 0, sizeof(fpu_register) ); *((uae_u32 *)&p[4]) = 0x80000000; } -static __inline__ uae_u32 IS_NEGATIVE(float80 p) +PRIVATE __inline__ uae_u32 FFPU IS_NEGATIVE (fpu_register const & f) { + uae_u8 * p = (uae_u8 *) &f; return( (p[9] & 0x80) != 0 ); } /* ---------------------------- Conversions ---------------------------- */ -static void signed_to_extended( uae_s32 x, float80 f ) REGPARAM; -static void signed_to_extended( uae_s32 x, float80 f ) +PRIVATE void FFPU signed_to_extended ( uae_s32 x, fpu_register & f ) { FPU_CONSISTENCY_CHECK_START(); @@ -582,18 +503,12 @@ static void signed_to_extended( uae_s32 x, float80 f ) FSTP TBYTE PTR [ESI] } */ - _ASM( "fildl %1\n" - "fstpt %0\n" - : "=m" (*f) - : "m" (x) - ); - + __asm__ __volatile__("fildl %1\n\tfstpt %0" : "=m" (f) : "m" (x)); D(bug("signed_to_extended (%X) = %s\r\n",(int)x,etos(f))); FPU_CONSISTENCY_CHECK_STOP("signed_to_extended"); } -static uae_s32 extended_to_signed_32( float80 f ) REGPARAM; -static uae_s32 extended_to_signed_32( float80 f ) +PRIVATE uae_s32 FFPU extended_to_signed_32 ( fpu_register const & f ) { FPU_CONSISTENCY_CHECK_START(); volatile uae_s32 tmp; @@ -606,26 +521,27 @@ static uae_s32 extended_to_signed_32( float80 f ) FNSTSW sw_temp } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fistpl %0\n" "fnstsw %1\n" : "=m" (tmp), "=m" (sw_temp) - : "m" (*f) + : "m" (f) ); if(sw_temp & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); + __asm__ __volatile__("fnclex"); if(sw_temp & (SW_OE|SW_UE|SW_DE|SW_IE)) { // Map SW_OE to OPERR. - sw |= SW_IE; - sw_accrued |= SW_IE; + x86_status_word |= SW_IE; + x86_status_word_accrued |= SW_IE; // Setting the value to zero might not be the right way to go, // but I'll leave it like this for now. tmp = 0; } if(sw_temp & SW_PE) { - sw |= SW_PE; - sw_accrued |= SW_PE; + x86_status_word |= SW_PE; + x86_status_word_accrued |= SW_PE; } } @@ -634,8 +550,7 @@ static uae_s32 extended_to_signed_32( float80 f ) return tmp; } -static uae_s16 extended_to_signed_16( float80 f ) REGPARAM; -static uae_s16 extended_to_signed_16( float80 f ) +PRIVATE uae_s16 FFPU extended_to_signed_16 ( fpu_register const & f ) { FPU_CONSISTENCY_CHECK_START(); volatile uae_s16 tmp; @@ -648,24 +563,25 @@ static uae_s16 extended_to_signed_16( float80 f ) FNSTSW sw_temp } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fistp %0\n" "fnstsw %1\n" : "=m" (tmp), "=m" (sw_temp) - : "m" (*f) + : "m" (f) ); if(sw_temp & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); + __asm__ __volatile__("fnclex"); if(sw_temp & (SW_OE|SW_UE|SW_DE|SW_IE)) { // Map SW_OE to OPERR. - sw |= SW_IE; - sw_accrued |= SW_IE; + x86_status_word |= SW_IE; + x86_status_word_accrued |= SW_IE; tmp = 0; } if(sw_temp & SW_PE) { - sw |= SW_PE; - sw_accrued |= SW_PE; + x86_status_word |= SW_PE; + x86_status_word_accrued |= SW_PE; } } @@ -674,8 +590,7 @@ static uae_s16 extended_to_signed_16( float80 f ) return tmp; } -static uae_s8 extended_to_signed_8( float80 f ) REGPARAM; -static uae_s8 extended_to_signed_8( float80 f ) +PRIVATE uae_s8 FFPU extended_to_signed_8 ( fpu_register const & f ) { FPU_CONSISTENCY_CHECK_START(); volatile uae_s16 tmp; @@ -688,30 +603,31 @@ static uae_s8 extended_to_signed_8( float80 f ) FNSTSW sw_temp } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fistp %0\n" "fnstsw %1\n" : "=m" (tmp), "=m" (sw_temp) - : "m" (*f) + : "m" (f) ); if(sw_temp & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); + __asm__ __volatile__("fnclex"); if(sw_temp & (SW_OE|SW_UE|SW_DE|SW_IE)) { // Map SW_OE to OPERR. - sw |= SW_IE; - sw_accrued |= SW_IE; + x86_status_word |= SW_IE; + x86_status_word_accrued |= SW_IE; tmp = 0; } if(sw_temp & SW_PE) { - sw |= SW_PE; - sw_accrued |= SW_PE; + x86_status_word |= SW_PE; + x86_status_word_accrued |= SW_PE; } } if(tmp > 127 || tmp < -128) { // OPERR - sw |= SW_IE; - sw_accrued |= SW_IE; + x86_status_word |= SW_IE; + x86_status_word_accrued |= SW_IE; } D(bug("extended_to_signed_8 (%s) = %X\r\n",etos(f),(int)tmp)); @@ -719,8 +635,7 @@ static uae_s8 extended_to_signed_8( float80 f ) return (uae_s8)tmp; } -static void double_to_extended( double x, float80 f ) REGPARAM; -static void double_to_extended( double x, float80 f ) +PRIVATE void FFPU double_to_extended ( double x, fpu_register & f ) { FPU_CONSISTENCY_CHECK_START(); @@ -730,20 +645,20 @@ static void double_to_extended( double x, float80 f ) FSTP TBYTE PTR [EDI] } */ - _ASM( "fldl %1\n" + __asm__ __volatile__( + "fldl %1\n" "fstpt %0\n" - : "=m" (*f) + : "=m" (f) : "m" (x) ); FPU_CONSISTENCY_CHECK_STOP("double_to_extended"); } -static double extended_to_double( float80 f ) REGPARAM; -static double extended_to_double( float80 f ) +PRIVATE fpu_double FFPU extended_to_double( fpu_register const & f ) { FPU_CONSISTENCY_CHECK_START(); - volatile double result; + double result; /* _asm { MOV ESI, [f] @@ -751,18 +666,18 @@ static double extended_to_double( float80 f ) FSTP QWORD PTR result } */ - _ASM( "fldt %1\n" + __asm__ __volatile__( + "fldt %1\n" "fstpl %0\n" : "=m" (result) - : "m" (*f) + : "m" (f) ); FPU_CONSISTENCY_CHECK_STOP("extended_to_double"); return result; } -static void to_single( uae_u32 src, float80 f ) REGPARAM; -static void to_single( uae_u32 src, float80 f ) +PRIVATE void FFPU to_single ( uae_u32 src, fpu_register & f ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -771,9 +686,10 @@ static void to_single( uae_u32 src, float80 f ) FSTP TBYTE PTR [ESI] } */ - _ASM( "flds %1\n" + __asm__ __volatile__( + "flds %1\n" "fstpt %0\n" - : "=m" (*f) + : "=m" (f) : "m" (src) ); @@ -782,11 +698,10 @@ static void to_single( uae_u32 src, float80 f ) } // TODO_BIGENDIAN -static void to_exten_no_normalize( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, float80 f ) REGPARAM; -static void to_exten_no_normalize( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, float80 f ) +PRIVATE void FFPU to_exten_no_normalize ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f ) { FPU_CONSISTENCY_CHECK_START(); - uae_u32 *p = (uae_u32 *)f; + uae_u32 *p = (uae_u32 *)&f; uae_u32 sign = (wrd1 & 0x80000000) >> 16; uae_u32 exp = (wrd1 >> 16) & 0x7fff; @@ -798,11 +713,10 @@ static void to_exten_no_normalize( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, flo FPU_CONSISTENCY_CHECK_STOP("to_exten_no_normalize"); } -static void to_exten( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, float80 f ) REGPARAM; -static void to_exten( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, float80 f ) +PRIVATE void FFPU to_exten ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f ) { FPU_CONSISTENCY_CHECK_START(); - uae_u32 *p = (uae_u32 *)f; + uae_u32 *p = (uae_u32 *)&f; uae_u32 sign = (wrd1 & 0x80000000) >> 16; uae_u32 exp = (wrd1 >> 16) & 0x7fff; @@ -843,8 +757,7 @@ static void to_exten( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, float80 f ) FPU_CONSISTENCY_CHECK_STOP("to_exten"); } -static void to_double( uae_u32 wrd1, uae_u32 wrd2, float80 f ) REGPARAM; -static void to_double( uae_u32 wrd1, uae_u32 wrd2, float80 f ) +PRIVATE void FFPU to_double ( uae_u32 wrd1, uae_u32 wrd2, fpu_register & f ) { FPU_CONSISTENCY_CHECK_START(); @@ -867,9 +780,10 @@ static void to_double( uae_u32 wrd1, uae_u32 wrd2, float80 f ) FSTP TBYTE PTR [EDI] } */ - _ASM( "fldl %1\n" + __asm__ __volatile__( + "fldl %1\n" "fstpt %0\n" - : "=m" (*f) + : "=m" (f) : "m" (src.q) ); @@ -877,8 +791,7 @@ static void to_double( uae_u32 wrd1, uae_u32 wrd2, float80 f ) FPU_CONSISTENCY_CHECK_STOP("to_double"); } -static uae_u32 from_single( float80 f ) REGPARAM; -static uae_u32 from_single( float80 f ) +PRIVATE uae_u32 FFPU from_single ( fpu_register const & f ) { FPU_CONSISTENCY_CHECK_START(); volatile uae_u32 dest; @@ -891,19 +804,20 @@ static uae_u32 from_single( float80 f ) FNSTSW sw_temp } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fstps %0\n" "fnstsw %1\n" : "=m" (dest), "=m" (sw_temp) - : "m" (*f) + : "m" (f) ); sw_temp &= SW_EXCEPTION_MASK; if(sw_temp) { // _asm FNCLEX asm("fnclex"); - sw = (sw & ~SW_EXCEPTION_MASK) | sw_temp; - sw_accrued |= sw_temp; + x86_status_word = (x86_status_word & ~SW_EXCEPTION_MASK) | sw_temp; + x86_status_word_accrued |= sw_temp; } D(bug("from_single (%s) = %X\r\n",etos(f),dest)); @@ -912,11 +826,10 @@ static uae_u32 from_single( float80 f ) } // TODO_BIGENDIAN -static void from_exten( float80 f, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3 ) REGPARAM; -static void from_exten( float80 f, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3 ) +PRIVATE void FFPU from_exten ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3 ) { FPU_CONSISTENCY_CHECK_START(); - uae_u32 *p = (uae_u32 *)f; + uae_u32 *p = (uae_u32 *)&f; *wrd3 = p[0]; *wrd2 = p[1]; *wrd1 = ( (uae_u32)*((uae_u16 *)&p[2]) ) << 16; @@ -925,8 +838,7 @@ static void from_exten( float80 f, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3 ) FPU_CONSISTENCY_CHECK_STOP("from_exten"); } -static void from_double( float80 f, uae_u32 *wrd1, uae_u32 *wrd2 ) REGPARAM; -static void from_double( float80 f, uae_u32 *wrd1, uae_u32 *wrd2 ) +PRIVATE void FFPU from_double ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2 ) { FPU_CONSISTENCY_CHECK_START(); volatile uae_u32 dest[2]; @@ -939,19 +851,20 @@ static void from_double( float80 f, uae_u32 *wrd1, uae_u32 *wrd2 ) FNSTSW sw_temp } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fstpl %0\n" "fnstsw %1\n" : "=m" (dest), "=m" (sw_temp) - : "m" (*f) + : "m" (f) ); sw_temp &= SW_EXCEPTION_MASK; if(sw_temp) { // _asm FNCLEX asm("fnclex"); - sw = (sw & ~SW_EXCEPTION_MASK) | sw_temp; - sw_accrued |= sw_temp; + x86_status_word = (x86_status_word & ~SW_EXCEPTION_MASK) | sw_temp; + x86_status_word_accrued |= sw_temp; } // TODO: There is a partial memory stall, nothing happens until FSTP retires. @@ -963,8 +876,7 @@ static void from_double( float80 f, uae_u32 *wrd1, uae_u32 *wrd2 ) FPU_CONSISTENCY_CHECK_STOP("from_double"); } -static void do_fmove( float80 dest, float80 src ) REGPARAM; -static void do_fmove( float80 dest, float80 src ) +PRIVATE void FFPU do_fmove ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -972,23 +884,23 @@ static void do_fmove( float80 dest, float80 src ) MOV EDI, [dest] FLD TBYTE PTR [ESI] FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" - : "=m" (sw), "=m" (*dest) - : "m" (*src) + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) ); FPU_CONSISTENCY_CHECK_STOP("do_fmove"); } /* -static void do_fmove_no_status( float80 dest, float80 src ) REGPARAM; -static void do_fmove_no_status( float80 dest, float80 src ) +PRIVATE void FFPU do_fmove_no_status ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); _asm { @@ -1004,8 +916,7 @@ static void do_fmove_no_status( float80 dest, float80 src ) /* ---------------------------- Operations ---------------------------- */ -static void do_fint( float80 dest, float80 src ) REGPARAM; -static void do_fint( float80 dest, float80 src ) +PRIVATE void FFPU do_fint ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -1014,49 +925,50 @@ static void do_fint( float80 dest, float80 src ) FLD TBYTE PTR [ESI] FRNDINT FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "frndint\n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" - : "=m" (sw), "=m" (*dest) - : "m" (*src) + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~(SW_EXCEPTION_MASK - SW_PE); - sw_accrued |= sw; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_PE); + x86_status_word_accrued |= x86_status_word; } FPU_CONSISTENCY_CHECK_STOP("do_fint"); } -static void do_fintrz( float80 dest, float80 src ) REGPARAM; -static void do_fintrz( float80 dest, float80 src ) +PRIVATE void FFPU do_fintrz ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); - volatile WORD cw_temp; + WORD cw_temp; /* _asm { MOV ESI, [src] MOV EDI, [dest] FSTCW cw_temp - and cw_temp, ~X86_ROUND_CONTROL_MASK + and cw_temp, ~X86_ROUNDING_MODE or cw_temp, CW_RC_ZERO FLDCW cw_temp FLD TBYTE PTR [ESI] FRNDINT FXAM - FNSTSW sw - FLDCW cw + FNSTSW x86_status_word + FLDCW x86_control_word FSTP TBYTE PTR [EDI] } */ - _ASM( "fstcw %0\n" - "andl $(~X86_ROUND_CONTROL_MASK), %0\n" + __asm__ __volatile__( + "fstcw %0\n" + "andl $(~X86_ROUNDING_MODE), %0\n" "orl $CW_RC_ZERO, %0\n" "fldcw %0\n" "fldt %3\n" @@ -1065,21 +977,20 @@ static void do_fintrz( float80 dest, float80 src ) "fnstsw %1\n" "fldcw %4\n" "fstpt %2\n" - : "+m" (cw_temp), "=m" (sw), "=m" (*dest) - : "m" (*src), "m" (cw) + : "+m" (cw_temp), "=m" (x86_status_word), "=m" (dest) + : "m" (src), "m" (x86_control_word) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~(SW_EXCEPTION_MASK - SW_PE); - sw_accrued |= sw; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_PE); + x86_status_word_accrued |= x86_status_word; } FPU_CONSISTENCY_CHECK_STOP("do_fintrz"); } -static void do_fsqrt( float80 dest, float80 src ) REGPARAM; -static void do_fsqrt( float80 dest, float80 src ) +PRIVATE void FFPU do_fsqrt ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -1088,60 +999,60 @@ static void do_fsqrt( float80 dest, float80 src ) FLD TBYTE PTR [ESI] FSQRT FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fsqrt \n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" - : "=m" (sw), "=m" (*dest) - : "m" (*src) + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); - sw_accrued |= sw; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); + x86_status_word_accrued |= x86_status_word; } FPU_CONSISTENCY_CHECK_STOP("do_fsqrt"); } -static void do_ftst( float80 src ) REGPARAM; -static void do_ftst( float80 src ) +PRIVATE void FFPU do_ftst ( fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { MOV ESI, [src] FLD TBYTE PTR [ESI] FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP ST(0) } */ - _ASM( "fldt %1\n" + __asm__ __volatile__( + "fldt %1\n" "fxam \n" "fnstsw %0\n" "fstp %%st(0)\n" - : "=m" (sw) - : "m" (*src) + : "=m" (x86_status_word) + : "m" (src) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~SW_EXCEPTION_MASK; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; } FPU_CONSISTENCY_CHECK_STOP("do_ftst"); } // These functions are calculated in 53 bits accuracy only. // Exception checking is not complete. -static void do_fsinh( float80 dest, float80 src ) REGPARAM; -static void do_fsinh( float80 dest, float80 src ) +PRIVATE void FFPU do_fsinh ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); double x, y; @@ -1152,8 +1063,7 @@ static void do_fsinh( float80 dest, float80 src ) FPU_CONSISTENCY_CHECK_STOP("do_fsinh"); } -static void do_flognp1( float80 dest, float80 src ) REGPARAM; -static void do_flognp1( float80 dest, float80 src ) +PRIVATE void FFPU do_flognp1 ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); double x, y; @@ -1164,8 +1074,7 @@ static void do_flognp1( float80 dest, float80 src ) FPU_CONSISTENCY_CHECK_STOP("do_flognp1"); } -static void do_fetoxm1( float80 dest, float80 src ) REGPARAM; -static void do_fetoxm1( float80 dest, float80 src ) +PRIVATE void FFPU do_fetoxm1 ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); double x, y; @@ -1176,8 +1085,7 @@ static void do_fetoxm1( float80 dest, float80 src ) FPU_CONSISTENCY_CHECK_STOP("do_fetoxm1"); } -static void do_ftanh( float80 dest, float80 src ) REGPARAM; -static void do_ftanh( float80 dest, float80 src ) +PRIVATE void FFPU do_ftanh ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); double x, y; @@ -1188,8 +1096,7 @@ static void do_ftanh( float80 dest, float80 src ) FPU_CONSISTENCY_CHECK_STOP("do_ftanh"); } -static void do_fatan( float80 dest, float80 src ) REGPARAM; -static void do_fatan( float80 dest, float80 src ) +PRIVATE void FFPU do_fatan ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); double x, y; @@ -1200,8 +1107,7 @@ static void do_fatan( float80 dest, float80 src ) FPU_CONSISTENCY_CHECK_STOP("do_fatan"); } -static void do_fasin( float80 dest, float80 src ) REGPARAM; -static void do_fasin( float80 dest, float80 src ) +PRIVATE void FFPU do_fasin ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); double x, y; @@ -1212,8 +1118,7 @@ static void do_fasin( float80 dest, float80 src ) FPU_CONSISTENCY_CHECK_STOP("do_fasin"); } -static void do_fatanh( float80 dest, float80 src ) REGPARAM; -static void do_fatanh( float80 dest, float80 src ) +PRIVATE void FFPU do_fatanh ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); double x, y; @@ -1224,8 +1129,7 @@ static void do_fatanh( float80 dest, float80 src ) FPU_CONSISTENCY_CHECK_STOP("do_fatanh"); } -static void do_fetox( float80 dest, float80 src ) REGPARAM; -static void do_fetox( float80 dest, float80 src ) +PRIVATE void FFPU do_fetox ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); double x, y; @@ -1236,8 +1140,7 @@ static void do_fetox( float80 dest, float80 src ) FPU_CONSISTENCY_CHECK_STOP("do_fetox"); } -static void do_ftwotox( float80 dest, float80 src ) REGPARAM; -static void do_ftwotox( float80 dest, float80 src ) +PRIVATE void FFPU do_ftwotox ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); double x, y; @@ -1248,8 +1151,7 @@ static void do_ftwotox( float80 dest, float80 src ) FPU_CONSISTENCY_CHECK_STOP("do_ftwotox"); } -static void do_ftentox( float80 dest, float80 src ) REGPARAM; -static void do_ftentox( float80 dest, float80 src ) +PRIVATE void FFPU do_ftentox ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); double x, y; @@ -1260,8 +1162,7 @@ static void do_ftentox( float80 dest, float80 src ) FPU_CONSISTENCY_CHECK_STOP("do_ftentox"); } -static void do_flogn( float80 dest, float80 src ) REGPARAM; -static void do_flogn( float80 dest, float80 src ) +PRIVATE void FFPU do_flogn ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); double x, y; @@ -1272,8 +1173,7 @@ static void do_flogn( float80 dest, float80 src ) FPU_CONSISTENCY_CHECK_STOP("do_flogn"); } -static void do_flog10( float80 dest, float80 src ) REGPARAM; -static void do_flog10( float80 dest, float80 src ) +PRIVATE void FFPU do_flog10 ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); double x, y; @@ -1284,8 +1184,7 @@ static void do_flog10( float80 dest, float80 src ) FPU_CONSISTENCY_CHECK_STOP("do_flog10"); } -static void do_flog2( float80 dest, float80 src ) REGPARAM; -static void do_flog2( float80 dest, float80 src ) +PRIVATE void FFPU do_flog2 ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); double x, y; @@ -1296,8 +1195,7 @@ static void do_flog2( float80 dest, float80 src ) FPU_CONSISTENCY_CHECK_STOP("do_flog2"); } -static void do_facos( float80 dest, float80 src ) REGPARAM; -static void do_facos( float80 dest, float80 src ) +PRIVATE void FFPU do_facos ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); double x, y; @@ -1308,8 +1206,7 @@ static void do_facos( float80 dest, float80 src ) FPU_CONSISTENCY_CHECK_STOP("do_facos"); } -static void do_fcosh( float80 dest, float80 src ) REGPARAM; -static void do_fcosh( float80 dest, float80 src ) +PRIVATE void FFPU do_fcosh ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); double x, y; @@ -1320,8 +1217,7 @@ static void do_fcosh( float80 dest, float80 src ) FPU_CONSISTENCY_CHECK_STOP("do_fcosh"); } -static void do_fsin( float80 dest, float80 src ) REGPARAM; -static void do_fsin( float80 dest, float80 src ) +PRIVATE void FFPU do_fsin ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -1330,29 +1226,29 @@ static void do_fsin( float80 dest, float80 src ) FLD TBYTE PTR [ESI] FSIN FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fsin \n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" - : "=m" (sw), "=m" (*dest) - : "m" (*src) + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); - sw_accrued |= sw; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); + x86_status_word_accrued |= x86_status_word; } FPU_CONSISTENCY_CHECK_STOP("do_fsin"); } // TODO: Should check for out-of-range condition (partial tangent) -static void do_ftan( float80 dest, float80 src ) REGPARAM; -static void do_ftan( float80 dest, float80 src ) +PRIVATE void FFPU do_ftan ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -1362,29 +1258,29 @@ static void do_ftan( float80 dest, float80 src ) FPTAN FSTP ST(0) ; pop 1.0 (the 8087/287 compatibility thing) FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fptan \n" "fstp %%st(0)\n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" - : "=m" (sw), "=m" (*dest) - : "m" (*src) + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE - SW_UE); - sw_accrued |= sw; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE - SW_UE); + x86_status_word_accrued |= x86_status_word; } FPU_CONSISTENCY_CHECK_STOP("do_ftan"); } -static void do_fabs( float80 dest, float80 src ) REGPARAM; -static void do_fabs( float80 dest, float80 src ) +PRIVATE void FFPU do_fabs ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -1393,28 +1289,28 @@ static void do_fabs( float80 dest, float80 src ) FLD TBYTE PTR [ESI] FABS FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fabs \n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" - : "=m" (sw), "=m" (*dest) - : "m" (*src) + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) ); // x86 fabs should not rise any exceptions (except stack underflow) - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~SW_EXCEPTION_MASK; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; } FPU_CONSISTENCY_CHECK_STOP("do_fabs"); } -static void do_fneg( float80 dest, float80 src ) REGPARAM; -static void do_fneg( float80 dest, float80 src ) +PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -1423,28 +1319,28 @@ static void do_fneg( float80 dest, float80 src ) FLD TBYTE PTR [ESI] FCHS FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fchs \n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" - : "=m" (sw), "=m" (*dest) - : "m" (*src) + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) ); // x86 fchs should not rise any exceptions (except stack underflow) - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~SW_EXCEPTION_MASK; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; } FPU_CONSISTENCY_CHECK_STOP("do_fneg"); } -static void do_fcos( float80 dest, float80 src ) REGPARAM; -static void do_fcos( float80 dest, float80 src ) +PRIVATE void FFPU do_fcos ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -1453,28 +1349,28 @@ static void do_fcos( float80 dest, float80 src ) FLD TBYTE PTR [ESI] FCOS FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fcos \n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" - : "=m" (sw), "=m" (*dest) - : "m" (*src) + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); - sw_accrued |= sw; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); + x86_status_word_accrued |= x86_status_word; } FPU_CONSISTENCY_CHECK_STOP("do_fcos"); } -static void do_fgetexp( float80 dest, float80 src ) REGPARAM; -static void do_fgetexp( float80 dest, float80 src ) +PRIVATE void FFPU do_fgetexp ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -1484,28 +1380,28 @@ static void do_fgetexp( float80 dest, float80 src ) FXTRACT FSTP ST(0) ; pop mantissa FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fxtract\n" "fstp %%st(0)\n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" - : "=m" (sw), "=m" (*dest) - : "m" (*src) + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~SW_EXCEPTION_MASK; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; } FPU_CONSISTENCY_CHECK_STOP("do_fgetexp"); } -static void do_fgetman( float80 dest, float80 src ) REGPARAM; -static void do_fgetman( float80 dest, float80 src ) +PRIVATE void FFPU do_fgetman ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -1514,29 +1410,29 @@ static void do_fgetman( float80 dest, float80 src ) FLD TBYTE PTR [ESI] FXTRACT FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] FSTP ST(0) ; pop exponent } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fxtract\n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" "fstp %%st(0)\n" - : "=m" (sw), "=m" (*dest) - : "m" (*src) + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~SW_EXCEPTION_MASK; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; } FPU_CONSISTENCY_CHECK_STOP("do_fgetman"); } -static void do_fdiv( float80 dest, float80 src ) REGPARAM; -static void do_fdiv( float80 dest, float80 src ) +PRIVATE void FFPU do_fdiv ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -1546,24 +1442,25 @@ static void do_fdiv( float80 dest, float80 src ) FLD TBYTE PTR [EDI] FDIV ST(0),ST(1) FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] FSTP ST(0) } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fldt %1\n" "fdiv %%st(1), %%st(0)\n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" "fstp %%st(0)\n" - : "=m" (sw), "+m" (*dest) - : "m" (*src) + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw_accrued |= sw; + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; } FPU_CONSISTENCY_CHECK_STOP("do_fdiv"); } @@ -1573,8 +1470,7 @@ static void do_fdiv( float80 dest, float80 src ) // Quotient Byte is loaded with the sign and least significant // seven bits of the quotient. -static void do_fmod( float80 dest, float80 src ) REGPARAM; -static void do_fmod( float80 dest, float80 src ) +PRIVATE void FFPU do_fmod ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -1583,16 +1479,18 @@ static void do_fmod( float80 dest, float80 src ) #if !USE_3_BIT_QUOTIENT WORD cw_temp; #endif - - uae_u32 sign = (dest[9] ^ src[9]) & 0x80; + + uae_u8 * dest_p = (uae_u8 *)&dest; + uae_u8 * src_p = (uae_u8 *)&src; + uae_u32 sign = (dest_p[9] ^ src_p[9]) & 0x80; /* _asm { MOV ESI, [src] MOV EDI, [dest] #if !USE_3_BIT_QUOTIENT - MOV CX, cw - AND CX, ~X86_ROUND_CONTROL_MASK + MOV CX, x86_control_word + AND CX, ~X86_ROUNDING_MODE OR CX, CW_RC_ZERO MOV cw_temp, CX FLDCW cw_temp @@ -1603,7 +1501,7 @@ static void do_fmod( float80 dest, float80 src ) FABS FISTP DWORD PTR quot FSTP ST(0) - FLDCW cw + FLDCW x86_control_word // TODO:Quotient // Should clear any possible exceptions here #endif @@ -1620,7 +1518,7 @@ partial_loop: FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] FSTP ST(0) @@ -1628,8 +1526,9 @@ partial_loop: #if !USE_3_BIT_QUOTIENT - _ASM( "movl %6, %%ecx\n" // %6: cw (read) - "andl $(~X86_ROUND_CONTROL_MASK), %%ecx\n" + __asm__ __volatile__( + "movl %6, %%ecx\n" // %6: x86_control_word (read) + "andl $(~X86_ROUNDING_MODE), %%ecx\n" "orl $CW_RC_ZERO, %%ecx\n" "movl %%ecx, %0\n" // %0: cw_temp (read/write) "fldcw %0\n" @@ -1648,17 +1547,18 @@ partial_loop: "testl $SW_C2, %2\n" "jne 0b\n" "fxam \n" - "fnstsw %3\n" // %3: sw (write) + "fnstsw %3\n" // %3: x86_status_word (write) "fstpt %4\n" "fstp %%st(0)\n" - : "+m" (cw_temp), "+m" (quot), "+m" (status), "=m" (sw), "+m" (*dest) - : "m" (*src), "m" (cw) + : "+m" (cw_temp), "+m" (quot), "+m" (status), "=m" (x86_status_word), "+m" (dest) + : "m" (src), "m" (x86_control_word) : "ecx" ); #else - _ASM( "fldt %3\n" + __asm__ __volatile__( + "fldt %3\n" "fldt %2\n" "0:\n" // partial_loop "fprem \n" @@ -1666,20 +1566,20 @@ partial_loop: "testl $SW_C2, %0\n" "jne 0b\n" "fxam \n" - "fnstsw %1\n" // %1: sw (write) + "fnstsw %1\n" // %1: x86_status_word (write) "fstpt %2\n" "fstp %%st(0)\n" - : "+m" (status), "=m" (sw), "+m" (*dest) - : "m" (*src) + : "+m" (status), "=m" (x86_status_word), "+m" (dest) + : "m" (src) ); #endif - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE); - sw_accrued |= sw; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE); + x86_status_word_accrued |= x86_status_word; } #if USE_3_BIT_QUOTIENT @@ -1687,16 +1587,15 @@ partial_loop: // SW_C3 Set to bit 1 (Q1) of the quotient. // SW_C0 Set to bit 2 (Q2) of the quotient. quot = ((status & SW_C0) >> 6) | ((status & SW_C3) >> 13) | ((status & SW_C1) >> 9); - sw_quotient = (sign | quot) << 16; + FPU fpsr.quotient = (sign | quot) << 16; #else - sw_quotient = (sign | (quot&0x7F)) << 16; + FPU fpsr.quotient = (sign | (quot&0x7F)) << 16; #endif FPU_CONSISTENCY_CHECK_STOP("do_fmod"); } -static void do_frem( float80 dest, float80 src ) REGPARAM; -static void do_frem( float80 dest, float80 src ) +PRIVATE void FFPU do_frem ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -1706,15 +1605,17 @@ static void do_frem( float80 dest, float80 src ) WORD cw_temp; #endif - uae_u32 sign = (dest[9] ^ src[9]) & 0x80; + uae_u8 * dest_p = (uae_u8 *)&dest; + uae_u8 * src_p = (uae_u8 *)&src; + uae_u32 sign = (dest_p[9] ^ src_p[9]) & 0x80; /* _asm { MOV ESI, [src] MOV EDI, [dest] #if !USE_3_BIT_QUOTIENT - MOV CX, cw - AND CX, ~X86_ROUND_CONTROL_MASK + MOV CX, x86_control_word + AND CX, ~X86_ROUNDING_MODE OR CX, CW_RC_NEAR MOV cw_temp, CX FLDCW cw_temp @@ -1725,7 +1626,7 @@ static void do_frem( float80 dest, float80 src ) FABS FISTP DWORD PTR quot FSTP ST(0) - FLDCW cw + FLDCW x86_control_word // TODO:Quotient // Should clear any possible exceptions here #endif @@ -1741,15 +1642,16 @@ partial_loop: JNE partial_loop FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] FSTP ST(0) } */ #if !USE_3_BIT_QUOTIENT - _ASM( "movl %6, %%ecx\n" // %6: cw (read) - "andl $(~X86_ROUND_CONTROL_MASK), %%ecx\n" + __asm__ __volatile__( + "movl %6, %%ecx\n" // %6: x86_control_word (read) + "andl $(~X86_ROUNDING_MODE), %%ecx\n" "orl $CW_RC_NEAR, %%ecx\n" "movl %%ecx, %0\n" // %0: cw_temp (read/write) "fldcw %0\n" @@ -1768,17 +1670,18 @@ partial_loop: "testl $SW_C2, %2\n" "jne 0b\n" "fxam \n" - "fnstsw %3\n" // %3: sw (write) + "fnstsw %3\n" // %3: x86_status_word (write) "fstpt %4\n" "fstp %%st(0)\n" - : "+m" (cw_temp), "+m" (quot), "+m" (status), "=m" (sw), "+m" (*dest) - : "m" (*src), "m" (cw) + : "+m" (cw_temp), "+m" (quot), "+m" (status), "=m" (x86_status_word), "+m" (dest) + : "m" (src), "m" (x86_control_word) : "ecx" ); #else - _ASM( "fldt %3\n" + __asm__ __volatile__( + "fldt %3\n" "fldt %2\n" "0:\n" // partial_loop "fprem1 \n" @@ -1786,20 +1689,20 @@ partial_loop: "testl $SW_C2, %0\n" "jne 0b\n" "fxam \n" - "fnstsw %1\n" // %1: sw (write) + "fnstsw %1\n" // %1: x86_status_word (write) "fstpt %2\n" "fstp %%st(0)\n" - : "+m" (status), "=m" (sw), "+m" (*dest) - : "m" (*src) + : "+m" (status), "=m" (x86_status_word), "+m" (dest) + : "m" (src) ); #endif - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE); - sw_accrued |= sw; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE); + x86_status_word_accrued |= x86_status_word; } #if USE_3_BIT_QUOTIENT @@ -1807,9 +1710,9 @@ partial_loop: // SW_C3 Set to bit 1 (Q1) of the quotient. // SW_C0 Set to bit 2 (Q2) of the quotient. quot = ((status & SW_C0) >> 6) | ((status & SW_C3) >> 13) | ((status & SW_C1) >> 9); - sw_quotient = (sign | quot) << 16; + FPU fpsr.quotient = (sign | quot) << 16; #else - sw_quotient = (sign | (quot&0x7F)) << 16; + FPU fpsr.quotient = (sign | (quot&0x7F)) << 16; #endif FPU_CONSISTENCY_CHECK_STOP("do_frem"); @@ -1817,15 +1720,16 @@ partial_loop: // Faster versions. The current rounding mode is already correct. #if !USE_3_BIT_QUOTIENT -static void do_fmod_dont_set_cw( float80 dest, float80 src ) REGPARAM; -static void do_fmod_dont_set_cw( float80 dest, float80 src ) +PRIVATE void FFPU do_fmod_dont_set_cw ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); volatile uint16 status; uae_u32 quot; - uae_u32 sign = (dest[9] ^ src[9]) & 0x80; + uae_u8 * dest_p = (uae_u8 *)&dest; + uae_u8 * src_p = (uae_u8 *)&src; + uae_u32 sign = (dest_p[9] ^ src_p[9]) & 0x80; _asm { MOV ESI, [src] @@ -1851,29 +1755,30 @@ partial_loop: JNE partial_loop FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] FSTP ST(0) } - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { _asm FNCLEX - sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE); - sw_accrued |= sw; + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE); + x86_status_word_accrued |= x86_status_word; } - sw_quotient = (sign | (quot&0x7F)) << 16; + FPU fpsr.quotient = (sign | (quot&0x7F)) << 16; FPU_CONSISTENCY_CHECK_STOP("do_fmod_dont_set_cw"); } -static void do_frem_dont_set_cw( float80 dest, float80 src ) REGPARAM; -static void do_frem_dont_set_cw( float80 dest, float80 src ) +PRIVATE void FFPU do_frem_dont_set_cw ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); volatile uint16 status; uae_u32 quot; - uae_u32 sign = (dest[9] ^ src[9]) & 0x80; + uae_u8 * dest_p = (uae_u8 *)&dest; + uae_u8 * src_p = (uae_u8 *)&src; + uae_u32 sign = (dest_p[9] ^ src_p[9]) & 0x80; _asm { MOV ESI, [src] @@ -1899,22 +1804,21 @@ partial_loop: JNE partial_loop FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] FSTP ST(0) } - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { _asm FNCLEX - sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE); - sw_accrued |= sw; + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE); + x86_status_word_accrued |= x86_status_word; } - sw_quotient = (sign | (quot&0x7F)) << 16; + FPU fpsr.quotient = (sign | (quot&0x7F)) << 16; FPU_CONSISTENCY_CHECK_STOP("do_frem_dont_set_cw"); } #endif //USE_3_BIT_QUOTIENT -static void do_fadd( float80 dest, float80 src ) REGPARAM; -static void do_fadd( float80 dest, float80 src ) +PRIVATE void FFPU do_fadd ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -1924,29 +1828,29 @@ static void do_fadd( float80 dest, float80 src ) FLD TBYTE PTR [EDI] FADD FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fldt %1\n" "fadd \n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" - : "=m" (sw), "+m" (*dest) - : "m" (*src) + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); - sw_accrued |= sw; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); + x86_status_word_accrued |= x86_status_word; } FPU_CONSISTENCY_CHECK_STOP("do_fadd"); } -static void do_fmul( float80 dest, float80 src ) REGPARAM; -static void do_fmul( float80 dest, float80 src ) +PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -1956,34 +1860,34 @@ static void do_fmul( float80 dest, float80 src ) FLD TBYTE PTR [EDI] FMUL FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fldt %1\n" "fmul \n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" - : "=m" (sw), "+m" (*dest) - : "m" (*src) + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw_accrued |= sw; + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; } FPU_CONSISTENCY_CHECK_STOP("do_fmul"); } -static void do_fsgldiv( float80 dest, float80 src ) REGPARAM; -static void do_fsgldiv( float80 dest, float80 src ) +PRIVATE void FFPU do_fsgldiv ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); - volatile WORD cw_temp; + WORD cw_temp; /* _asm { FSTCW cw_temp - and cw_temp, ~X86_PRECISION_CONTROL_MASK + and cw_temp, ~X86_ROUNDING_PRECISION or cw_temp, PRECISION_CONTROL_SINGLE FLDCW cw_temp @@ -1993,13 +1897,14 @@ static void do_fsgldiv( float80 dest, float80 src ) FLD TBYTE PTR [EDI] FDIV ST(0),ST(1) FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] FSTP ST(0) - FLDCW cw + FLDCW x86_control_word } */ - _ASM( "fstcw %0\n" - "andl $(~X86_PRECISION_CONTROL_MASK), %0\n" + __asm__ __volatile__( + "fstcw %0\n" + "andl $(~X86_ROUNDING_PRECISION), %0\n" "orl $PRECISION_CONTROL_SINGLE, %0\n" "fldcw %0\n" "fldt %3\n" @@ -2010,19 +1915,18 @@ static void do_fsgldiv( float80 dest, float80 src ) "fstpt %2\n" "fstp %%st(0)\n" "fldcw %4\n" - : "+m" (cw_temp), "=m" (sw), "+m" (*dest) - : "m" (*src), "m" (cw) + : "+m" (cw_temp), "=m" (x86_status_word), "+m" (dest) + : "m" (src), "m" (x86_control_word) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw_accrued |= sw; + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; } FPU_CONSISTENCY_CHECK_STOP("do_fsgldiv"); } -static void do_fscale( float80 dest, float80 src ) REGPARAM; -static void do_fscale( float80 dest, float80 src ) +PRIVATE void FFPU do_fscale ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -2032,38 +1936,38 @@ static void do_fscale( float80 dest, float80 src ) FLD TBYTE PTR [EDI] FSCALE FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] FSTP ST(0) } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fldt %1\n" "fscale \n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" "fstp %%st(0)\n" - : "=m" (sw), "+m" (*dest) - : "m" (*src) + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~(SW_EXCEPTION_MASK - SW_UE - SW_OE); - sw_accrued |= sw; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_UE - SW_OE); + x86_status_word_accrued |= x86_status_word; } FPU_CONSISTENCY_CHECK_STOP("do_fscale"); } -static void do_fsglmul( float80 dest, float80 src ) REGPARAM; -static void do_fsglmul( float80 dest, float80 src ) +PRIVATE void FFPU do_fsglmul ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); - volatile WORD cw_temp; + WORD cw_temp; /* _asm { FSTCW cw_temp - and cw_temp, ~X86_PRECISION_CONTROL_MASK + and cw_temp, ~X86_ROUNDING_PRECISION or cw_temp, PRECISION_CONTROL_SINGLE FLDCW cw_temp @@ -2073,13 +1977,14 @@ static void do_fsglmul( float80 dest, float80 src ) FLD TBYTE PTR [EDI] FMUL FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] - FLDCW cw + FLDCW x86_control_word } */ - _ASM( "fstcw %0\n" - "andl $(~X86_PRECISION_CONTROL_MASK), %0\n" + __asm__ __volatile__( + "fstcw %0\n" + "andl $(~X86_ROUNDING_PRECISION), %0\n" "orl $PRECISION_CONTROL_SINGLE, %0\n" "fldcw %0\n" "fldt %3\n" @@ -2089,19 +1994,18 @@ static void do_fsglmul( float80 dest, float80 src ) "fnstsw %1\n" "fstpt %2\n" "fldcw %4\n" - : "+m" (cw_temp), "=m" (sw), "+m" (*dest) - : "m" (*src), "m" (sw) + : "+m" (cw_temp), "=m" (x86_status_word), "+m" (dest) + : "m" (src), "m" (x86_status_word) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw_accrued |= sw; + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; } FPU_CONSISTENCY_CHECK_STOP("do_fsglmul"); } -static void do_fsub( float80 dest, float80 src ) REGPARAM; -static void do_fsub( float80 dest, float80 src ) +PRIVATE void FFPU do_fsub ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -2111,31 +2015,31 @@ static void do_fsub( float80 dest, float80 src ) FLD TBYTE PTR [EDI] FSUB ST(0),ST(1) FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] FSTP ST(0) } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fldt %1\n" "fsub %%st(1), %%st(0)\n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" "fstp %%st(0)\n" - : "=m" (sw), "+m" (*dest) - : "m" (*src) + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); - sw_accrued |= sw; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); + x86_status_word_accrued |= x86_status_word; } FPU_CONSISTENCY_CHECK_STOP("do_fsub"); } -static void do_fsincos( float80 dest_sin, float80 dest_cos, float80 src ) REGPARAM; -static void do_fsincos( float80 dest_sin, float80 dest_cos, float80 src ) +PRIVATE void FFPU do_fsincos ( fpu_register & dest_sin, fpu_register & dest_cos, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -2146,31 +2050,31 @@ static void do_fsincos( float80 dest_sin, float80 dest_cos, float80 src ) FSTP TBYTE PTR [EDI] FXAM MOV EDI, [dest_sin] - FNSTSW sw + FNSTSW x86_status_word FSTP TBYTE PTR [EDI] FSTP ST(0) } */ - _ASM( "fldt %3\n" + __asm__ __volatile__( + "fldt %3\n" "fsincos\n" "fstpt %1\n" "fxam \n" "fnstsw %0\n" "fstpt %2\n" "fstp %%st(0)\n" - : "=m" (sw), "=m" (*dest_cos), "=m" (*dest_sin) - : "m" (*src) + : "=m" (x86_status_word), "=m" (dest_cos), "=m" (dest_sin) + : "m" (src) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_PE); - sw_accrued |= sw; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_PE); + x86_status_word_accrued |= x86_status_word; } FPU_CONSISTENCY_CHECK_STOP("do_fsincos"); } -static void do_fcmp( float80 dest, float80 src ) REGPARAM; -static void do_fcmp( float80 dest, float80 src ) +PRIVATE void FFPU do_fcmp ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { @@ -2180,31 +2084,31 @@ static void do_fcmp( float80 dest, float80 src ) FLD TBYTE PTR [EDI] FSUB ST(0),ST(1) FXAM - FNSTSW sw + FNSTSW x86_status_word FSTP ST(0) FSTP ST(0) } */ - _ASM( "fldt %2\n" + __asm__ __volatile__( + "fldt %2\n" "fldt %1\n" "fsub %%st(1), %%st(0)\n" "fxam \n" "fnstsw %0\n" "fstp %%st(0)\n" "fstp %%st(0)\n" - : "=m" (sw) - : "m" (*dest), "m" (*src) + : "=m" (x86_status_word) + : "m" (dest), "m" (src) ); - if(sw & SW_EXCEPTION_MASK) { + if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); - sw &= ~SW_EXCEPTION_MASK; + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; } FPU_CONSISTENCY_CHECK_STOP("do_fcmp"); } // More or less original. Should be reviewed. -static double to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) REGPARAM; -static double to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) +PRIVATE fpu_double FFPU to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) { FPU_CONSISTENCY_CHECK_START(); @@ -2252,8 +2156,7 @@ static double to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) } // More or less original. Should be reviewed. -static void from_pack(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) REGPARAM; -static void from_pack(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) +PRIVATE void FFPU from_pack (fpu_double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) { FPU_CONSISTENCY_CHECK_START(); @@ -2308,15 +2211,15 @@ static void from_pack(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3 D(bug("from_pack(%.04f) = %X,%X,%X\r\n",(float)src,*wrd1,*wrd2,*wrd3)); - volatile WORD sw_temp; + WORD sw_temp; // _asm FNSTSW sw_temp - _ASM("fnstsw %0" : "=m" (sw_temp)); + __asm__ __volatile__("fnstsw %0" : "=m" (sw_temp)); if(sw_temp & SW_EXCEPTION_MASK) { // _asm FNCLEX - _ASM("fnclex"); + __asm__ __volatile__("fnclex"); if(sw_temp & SW_PE) { - sw |= SW_PE; - sw_accrued |= SW_PE; + x86_status_word |= SW_PE; + x86_status_word_accrued |= SW_PE; } } @@ -2326,25 +2229,24 @@ static void from_pack(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3 cleared otherwise. */ if(exponent_digit_count > 3) { - sw |= SW_IE; - sw_accrued |= SW_IE; + x86_status_word |= SW_IE; + x86_status_word_accrued |= SW_IE; } FPU_CONSISTENCY_CHECK_STOP("from_pack"); } -static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; -static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; - -static int get_fp_value (uae_u32 opcode, uae_u16 extra, float80 src) REGPARAM; -static int get_fp_value (uae_u32 opcode, uae_u16 extra, float80 src) +PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src) { + static const int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; + static const int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; + // D(bug("get_fp_value(%X,%X)\r\n",(int)opcode,(int)extra)); // dump_first_bytes( regs.pc_p-4, 16 ); if ((extra & 0x4000) == 0) { - memcpy( src, fp_reg[(extra >> 10) & 7], sizeof(float80_s) ); - // do_fmove_no_status( src, fp_reg[(extra >> 10) & 7] ); + memcpy( &src, &FPU registers[(extra >> 10) & 7], sizeof(fpu_register) ); +// do_fmove_no_status( src, FPU registers[(extra >> 10) & 7] ); return 1; } @@ -2484,19 +2386,21 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, float80 src) return 0; } - // D(bug("get_fp_value result = %.04f\r\n",(float)*src)); + // D(bug("get_fp_value result = %.04f\r\n",(float)src)); return 1; } -static int put_fp_value (float80 value, uae_u32 opcode, uae_u16 extra) REGPARAM; -static int put_fp_value (float80 value, uae_u32 opcode, uae_u16 extra) +PRIVATE int FFPU put_fp_value (fpu_register const & value, uae_u32 opcode, uae_u32 extra) { + static const int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; + static const int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; + // D(bug("put_fp_value(%.04f,%X,%X)\r\n",(float)value,(int)opcode,(int)extra)); if ((extra & 0x4000) == 0) { int dest_reg = (extra >> 10) & 7; - do_fmove( fp_reg[dest_reg], value ); + do_fmove( FPU registers[dest_reg], value ); build_ex_status(); return 1; } @@ -2507,7 +2411,7 @@ static int put_fp_value (float80 value, uae_u32 opcode, uae_u16 extra) uae_u32 ad = 0xffffffff; // Clear exception status - sw &= ~SW_EXCEPTION_MASK; + x86_status_word &= ~SW_EXCEPTION_MASK; switch ((uae_u8)mode) { case 0: @@ -2585,10 +2489,10 @@ static int put_fp_value (float80 value, uae_u32 opcode, uae_u16 extra) uae_u32 wrd1, wrd2, wrd3; from_exten(value, &wrd1, &wrd2, &wrd3); - sw &= ~SW_EXCEPTION_MASK; + x86_status_word &= ~SW_EXCEPTION_MASK; if(wrd3) { // TODO: not correct! Just a "smart" guess. - sw |= SW_PE; - sw_accrued |= SW_PE; + x86_status_word |= SW_PE; + x86_status_word_accrued |= SW_PE; } put_long (ad, wrd1); @@ -2629,8 +2533,7 @@ static int put_fp_value (float80 value, uae_u32 opcode, uae_u16 extra) return 1; } -static int get_fp_ad(uae_u32 opcode, uae_u32 * ad) REGPARAM; -static int get_fp_ad(uae_u32 opcode, uae_u32 * ad) +PRIVATE int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) { int mode = (opcode >> 3) & 7; int reg = opcode & 7; @@ -2644,7 +2547,7 @@ static int get_fp_ad(uae_u32 opcode, uae_u32 * ad) m68k_setpc (m68k_getpc () - 4); } op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return 0; case 2: *ad = m68k_areg (regs, reg); @@ -2687,21 +2590,26 @@ static int get_fp_ad(uae_u32 opcode, uae_u32 * ad) m68k_setpc (m68k_getpc () - 4); } op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return 0; } } return 1; } -static int fpp_cond(uae_u32 opcode, int condition) REGPARAM; -static int fpp_cond(uae_u32 opcode, int condition) +#if FPU_DEBUG +#define CONDRET(s,x) D(bug("fpp_cond %s = %d\r\n",s,(uint32)(x))); return (x) +#else +#define CONDRET(s,x) return (x) +#endif + +PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition) { -#define N (sw & SW_N) -#define Z ((sw & (SW_Z_I_NAN_MASK)) == SW_Z) -#define I ((sw & (SW_Z_I_NAN_MASK)) == (SW_I)) -#define NotANumber ((sw & (SW_Z_I_NAN_MASK)) == SW_NAN) +#define N (x86_status_word & SW_N) +#define Z ((x86_status_word & (SW_Z_I_NAN_MASK)) == SW_Z) +#define I ((x86_status_word & (SW_Z_I_NAN_MASK)) == (SW_I)) +#define NotANumber ((x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN) switch (condition) { // Common Tests, no BSUN @@ -2802,7 +2710,7 @@ static int fpp_cond(uae_u32 opcode, int condition) } -void REGPARAM2 fdbcc_opp(uae_u32 opcode, uae_u16 extra) +PUBLIC void REGPARAM2 FFPU fpuop_dbcc(uae_u32 opcode, uae_u32 extra) { uaecptr pc = (uae_u32) m68k_getpc (); uae_s32 disp = (uae_s32) (uae_s16) next_iword(); @@ -2826,7 +2734,7 @@ void REGPARAM2 fdbcc_opp(uae_u32 opcode, uae_u16 extra) } } -void REGPARAM2 fscc_opp(uae_u32 opcode, uae_u16 extra) +PUBLIC void REGPARAM2 FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) { uae_u32 ad; int cc; @@ -2848,7 +2756,7 @@ void REGPARAM2 fscc_opp(uae_u32 opcode, uae_u16 extra) } } -void REGPARAM2 ftrapcc_opp(uae_u32 opcode, uaecptr oldpc) +PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) { int cc; @@ -2870,7 +2778,7 @@ void REGPARAM2 ftrapcc_opp(uae_u32 opcode, uaecptr oldpc) } // NOTE that we get here also when there is a FNOP (nontrapping false, displ 0) -void REGPARAM2 fbcc_opp(uae_u32 opcode, uaecptr pc, uae_u32 extra) +PUBLIC void REGPARAM2 FFPU fpuop_bcc(uae_u32 opcode, uaecptr pc, uae_u32 extra) { int cc; @@ -2889,7 +2797,7 @@ void REGPARAM2 fbcc_opp(uae_u32 opcode, uaecptr pc, uae_u32 extra) // FSAVE has no post-increment // 0x1f180000 == IDLE state frame, coprocessor version number 1F -void REGPARAM2 fsave_opp(uae_u32 opcode) +PUBLIC void REGPARAM2 FFPU fpuop_save(uae_u32 opcode) { uae_u32 ad; int incr = (opcode & 0x38) == 0x20 ? -1 : 1; @@ -2898,7 +2806,7 @@ void REGPARAM2 fsave_opp(uae_u32 opcode) D(bug("fsave_opp at %08lx\r\n", m68k_getpc ())); if (get_fp_ad(opcode, &ad)) { - if (is_integral_68040_fpu) { + if (FPU is_integral) { // Put 4 byte 68040 IDLE frame. if (incr < 0) { ad -= 4; @@ -2943,29 +2851,29 @@ void REGPARAM2 fsave_opp(uae_u32 opcode) } } -static void do_null_frestore() +PRIVATE void FFPU do_null_frestore () { // A null-restore operation sets FP7-FP0 positive, nonsignaling NANs. for( int i=0; i<8; i++ ) { - MAKE_NAN( fp_reg[i] ); + MAKE_NAN( FPU registers[i] ); } - regs.fpiar = 0; - regs.fpcr = 0; - regs.fpsr = 0; + FPU instruction_address = 0; + set_fpcr(0); + set_fpsr(0); - sw = SW_INITIAL; - sw_accrued = 0; - sw_quotient = 0; + x86_status_word = SW_INITIAL; + x86_status_word_accrued = 0; + FPU fpsr.quotient = 0; - cw = CW_INITIAL; -/* _asm FLDCW cw + x86_control_word = CW_INITIAL; +/* _asm FLDCW x86_control_word _asm FNCLEX */ - _ASM("fldcw %0\n\tfnclex" : : "m" (cw)); + __asm__ __volatile__("fldcw %0\n\tfnclex" : : "m" (x86_control_word)); } // FSAVE has no pre-decrement -void REGPARAM2 frestore_opp(uae_u32 opcode) +PUBLIC void REGPARAM2 FFPU fpuop_restore(uae_u32 opcode) { uae_u32 ad; uae_u32 d; @@ -2974,7 +2882,7 @@ void REGPARAM2 frestore_opp(uae_u32 opcode) D(bug("frestore_opp at %08lx\r\n", m68k_getpc ())); if (get_fp_ad(opcode, &ad)) { - if (is_integral_68040_fpu) { + if (FPU is_integral) { // 68040 if (incr < 0) { D(bug("PROBLEM: frestore_opp incr < 0\r\n")); @@ -3067,7 +2975,7 @@ void REGPARAM2 frestore_opp(uae_u32 opcode) /* ---------------------------- Old-style interface ---------------------------- */ // #ifndef OPTIMIZED_8BIT_MEMORY_ACCESS -void REGPARAM2 fpp_opp(uae_u32 opcode, uae_u16 extra) +PUBLIC void REGPARAM2 FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) { uae_u32 mask = (extra & 0xFC7F) | ((opcode & 0x0038) << 4); (*fpufunctbl[mask])(opcode,extra); @@ -3077,7 +2985,7 @@ void REGPARAM2 fpp_opp(uae_u32 opcode, uae_u16 extra) /* ---------------------------- Illegal ---------------------------- */ -void REGPARAM2 fpuop_illg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_illg( uae_u32 opcode, uae_u32 extra ) { D(bug("ILLEGAL F OP 2 %X\r\n",opcode)); @@ -3088,17 +2996,17 @@ void REGPARAM2 fpuop_illg( uae_u32 opcode, uae_u16 extra ) m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); } /* ---------------------------- FPP -> ---------------------------- */ -void REGPARAM2 fpuop_fmove_2_ea( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmove_2_ea( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVE -> \r\n")); - if (put_fp_value (fp_reg[(extra >> 7) & 7], opcode, extra) == 0) { + if (put_fp_value (FPU registers[(extra >> 7) & 7], opcode, extra) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); } @@ -3115,822 +3023,770 @@ void REGPARAM2 fpuop_fmove_2_ea( uae_u32 opcode, uae_u16 extra ) _asm FNSTSW sw_temp if(sw_temp & SW_PE) { _asm FNCLEX - sw |= SW_PE; - sw_accrued |= SW_PE; + x86_status_word |= SW_PE; + x86_status_word_accrued |= SW_PE; } */ - dump_fp_regs( "END "); + dump_registers( "END "); } /* ---------------------------- CONTROL REGS -> Dreg ---------------------------- */ -void REGPARAM2 fpuop_fmovem_none_2_Dreg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Dreg( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVEM control(none) -> D%d\r\n", opcode & 7)); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_fpiar_2_Dreg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ) { - D(bug("FMOVEM regs.fpiar (%X) -> D%d\r\n", regs.fpiar, opcode & 7)); - m68k_dreg (regs, opcode & 7) = regs.fpiar; - dump_fp_regs( "END "); + D(bug("FMOVEM FPU instruction_address (%X) -> D%d\r\n", FPU instruction_address, opcode & 7)); + m68k_dreg (regs, opcode & 7) = FPU instruction_address; + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_fpsr_2_Dreg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra ) { - to_fpsr(); - D(bug("FMOVEM regs.fpsr (%X) -> D%d\r\n", regs.fpsr, opcode & 7)); - m68k_dreg (regs, opcode & 7) = regs.fpsr; - dump_fp_regs( "END "); + D(bug("FMOVEM regs.FPU fpsr (%X) -> D%d\r\n", get_fpsr(), opcode & 7)); + m68k_dreg (regs, opcode & 7) = get_fpsr(); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_fpcr_2_Dreg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Dreg( uae_u32 opcode, uae_u32 extra ) { - D(bug("FMOVEM regs.fpcr (%X) -> D%d\r\n", regs.fpcr, opcode & 7)); - m68k_dreg (regs, opcode & 7) = regs.fpcr; - dump_fp_regs( "END "); + D(bug("FMOVEM regs.FPU fpcr (%X) -> D%d\r\n", get_fpcr(), opcode & 7)); + m68k_dreg (regs, opcode & 7) = get_fpcr(); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ) { - to_fpsr(); - D(bug("FMOVEM regs.fpsr (%X) -> D%d\r\n", regs.fpsr, opcode & 7)); - m68k_dreg (regs, opcode & 7) = regs.fpsr; - D(bug("FMOVEM regs.fpiar (%X) -> D%d\r\n", regs.fpiar, opcode & 7)); - m68k_dreg (regs, opcode & 7) = regs.fpiar; - dump_fp_regs( "END "); + D(bug("FMOVEM regs.FPU fpsr (%X) -> D%d\r\n", get_fpsr(), opcode & 7)); + m68k_dreg (regs, opcode & 7) = get_fpsr(); + D(bug("FMOVEM FPU instruction_address (%X) -> D%d\r\n", FPU instruction_address, opcode & 7)); + m68k_dreg (regs, opcode & 7) = FPU instruction_address; + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_fpcr_fpiar_2_Dreg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ) { - D(bug("FMOVEM regs.fpcr (%X) -> D%d\r\n", regs.fpcr, opcode & 7)); - m68k_dreg (regs, opcode & 7) = regs.fpcr; - D(bug("FMOVEM regs.fpiar (%X) -> D%d\r\n", regs.fpiar, opcode & 7)); - m68k_dreg (regs, opcode & 7) = regs.fpiar; - dump_fp_regs( "END "); + D(bug("FMOVEM regs.FPU fpcr (%X) -> D%d\r\n", get_fpcr(), opcode & 7)); + m68k_dreg (regs, opcode & 7) = get_fpcr(); + D(bug("FMOVEM FPU instruction_address (%X) -> D%d\r\n", FPU instruction_address, opcode & 7)); + m68k_dreg (regs, opcode & 7) = FPU instruction_address; + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_fpcr_fpsr_2_Dreg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra ) { - D(bug("FMOVEM regs.fpcr (%X) -> D%d\r\n", regs.fpcr, opcode & 7)); - m68k_dreg (regs, opcode & 7) = regs.fpcr; - to_fpsr(); - D(bug("FMOVEM regs.fpsr (%X) -> D%d\r\n", regs.fpsr, opcode & 7)); - m68k_dreg (regs, opcode & 7) = regs.fpsr; - dump_fp_regs( "END "); + D(bug("FMOVEM regs.FPU fpcr (%X) -> D%d\r\n", get_fpcr(), opcode & 7)); + m68k_dreg (regs, opcode & 7) = get_fpcr(); + D(bug("FMOVEM regs.FPU fpsr (%X) -> D%d\r\n", get_fpsr(), opcode & 7)); + m68k_dreg (regs, opcode & 7) = get_fpsr(); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_fpcr_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ) { - D(bug("FMOVEM regs.fpcr (%X) -> D%d\r\n", regs.fpcr, opcode & 7)); - m68k_dreg (regs, opcode & 7) = regs.fpcr; - to_fpsr(); - D(bug("FMOVEM regs.fpsr (%X) -> D%d\r\n", regs.fpsr, opcode & 7)); - m68k_dreg (regs, opcode & 7) = regs.fpsr; - D(bug("FMOVEM regs.fpiar (%X) -> D%d\r\n", regs.fpiar, opcode & 7)); - m68k_dreg (regs, opcode & 7) = regs.fpiar; - dump_fp_regs( "END "); + D(bug("FMOVEM regs.FPU fpcr (%X) -> D%d\r\n", get_fpcr(), opcode & 7)); + m68k_dreg (regs, opcode & 7) = get_fpcr(); + D(bug("FMOVEM regs.FPU fpsr (%X) -> D%d\r\n", get_fpsr(), opcode & 7)); + m68k_dreg (regs, opcode & 7) = get_fpsr(); + D(bug("FMOVEM FPU instruction_address (%X) -> D%d\r\n", FPU instruction_address, opcode & 7)); + m68k_dreg (regs, opcode & 7) = FPU instruction_address; + dump_registers( "END "); } /* ---------------------------- Dreg -> CONTROL REGS ---------------------------- */ -void REGPARAM2 fpuop_fmovem_Dreg_2_none( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_none( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVEM D%d -> control(none)\r\n", opcode & 7)); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Dreg_2_fpiar( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpiar( uae_u32 opcode, uae_u32 extra ) { - regs.fpiar = m68k_dreg (regs, opcode & 7); - D(bug("FMOVEM D%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar)); - dump_fp_regs( "END "); + FPU instruction_address = m68k_dreg (regs, opcode & 7); + D(bug("FMOVEM D%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Dreg_2_fpsr( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr( uae_u32 opcode, uae_u32 extra ) { - regs.fpsr = m68k_dreg (regs, opcode & 7); - from_fpsr(); - D(bug("FMOVEM D%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr)); - dump_fp_regs( "END "); + set_fpsr( m68k_dreg (regs, opcode & 7) ); + D(bug("FMOVEM D%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Dreg_2_fpsr_fpiar( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ) { - regs.fpsr = m68k_dreg (regs, opcode & 7); - from_fpsr(); - D(bug("FMOVEM D%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr)); - regs.fpiar = m68k_dreg (regs, opcode & 7); - D(bug("FMOVEM D%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar)); - dump_fp_regs( "END "); + set_fpsr( m68k_dreg (regs, opcode & 7) ); + D(bug("FMOVEM D%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); + FPU instruction_address = m68k_dreg (regs, opcode & 7); + D(bug("FMOVEM D%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Dreg_2_fpcr( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr( uae_u32 opcode, uae_u32 extra ) { - regs.fpcr = m68k_dreg (regs, opcode & 7); - set_host_fpu_control_word(); - D(bug("FMOVEM D%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr)); - dump_fp_regs( "END "); + set_fpcr( m68k_dreg (regs, opcode & 7) ); + D(bug("FMOVEM D%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Dreg_2_fpcr_fpiar( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra ) { - regs.fpcr = m68k_dreg (regs, opcode & 7); - set_host_fpu_control_word(); - D(bug("FMOVEM D%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr)); - regs.fpiar = m68k_dreg (regs, opcode & 7); - D(bug("FMOVEM D%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar)); - dump_fp_regs( "END "); + set_fpcr( m68k_dreg (regs, opcode & 7) ); + D(bug("FMOVEM D%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); + FPU instruction_address = m68k_dreg (regs, opcode & 7); + D(bug("FMOVEM D%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Dreg_2_fpcr_fpsr( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra ) { - regs.fpcr = m68k_dreg (regs, opcode & 7); - set_host_fpu_control_word(); - D(bug("FMOVEM D%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr)); - regs.fpsr = m68k_dreg (regs, opcode & 7); - from_fpsr(); - D(bug("FMOVEM D%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr)); - dump_fp_regs( "END "); + set_fpcr( m68k_dreg (regs, opcode & 7) ); + D(bug("FMOVEM D%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); + set_fpsr( m68k_dreg (regs, opcode & 7) ); + D(bug("FMOVEM D%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Dreg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ) { - regs.fpcr = m68k_dreg (regs, opcode & 7); - set_host_fpu_control_word(); - D(bug("FMOVEM D%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr)); - regs.fpsr = m68k_dreg (regs, opcode & 7); - from_fpsr(); - D(bug("FMOVEM D%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr)); - regs.fpiar = m68k_dreg (regs, opcode & 7); - D(bug("FMOVEM D%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar)); - dump_fp_regs( "END "); + set_fpcr( m68k_dreg (regs, opcode & 7) ); + D(bug("FMOVEM D%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); + set_fpsr( m68k_dreg (regs, opcode & 7) ); + D(bug("FMOVEM D%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); + FPU instruction_address = m68k_dreg (regs, opcode & 7); + D(bug("FMOVEM D%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); + dump_registers( "END "); } /* ---------------------------- CONTROL REGS -> Areg ---------------------------- */ -void REGPARAM2 fpuop_fmovem_none_2_Areg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Areg( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVEM control(none) -> A%d\r\n", opcode & 7)); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_fpiar_2_Areg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ) { - D(bug("FMOVEM regs.fpiar (%X) -> A%d\r\n", regs.fpiar, opcode & 7)); - m68k_areg (regs, opcode & 7) = regs.fpiar; - dump_fp_regs( "END "); + D(bug("FMOVEM FPU instruction_address (%X) -> A%d\r\n", FPU instruction_address, opcode & 7)); + m68k_areg (regs, opcode & 7) = FPU instruction_address; + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_fpsr_2_Areg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra ) { - to_fpsr(); - D(bug("FMOVEM regs.fpsr (%X) -> A%d\r\n", regs.fpsr, opcode & 7)); - m68k_areg (regs, opcode & 7) = regs.fpsr; - dump_fp_regs( "END "); + D(bug("FMOVEM regs.FPU fpsr (%X) -> A%d\r\n", get_fpsr(), opcode & 7)); + m68k_areg (regs, opcode & 7) = get_fpsr(); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_fpcr_2_Areg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Areg( uae_u32 opcode, uae_u32 extra ) { - D(bug("FMOVEM regs.fpcr (%X) -> A%d\r\n", regs.fpcr, opcode & 7)); - m68k_areg (regs, opcode & 7) = regs.fpcr; - dump_fp_regs( "END "); + D(bug("FMOVEM regs.FPU fpcr (%X) -> A%d\r\n", get_fpcr(), opcode & 7)); + m68k_areg (regs, opcode & 7) = get_fpcr(); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ) { - to_fpsr(); - D(bug("FMOVEM regs.fpsr (%X) -> A%d\r\n", regs.fpsr, opcode & 7)); - m68k_areg (regs, opcode & 7) = regs.fpsr; - D(bug("FMOVEM regs.fpiar (%X) -> A%d\r\n", regs.fpiar, opcode & 7)); - m68k_areg (regs, opcode & 7) = regs.fpiar; - dump_fp_regs( "END "); + D(bug("FMOVEM regs.FPU fpsr (%X) -> A%d\r\n", get_fpsr(), opcode & 7)); + m68k_areg (regs, opcode & 7) = get_fpsr(); + D(bug("FMOVEM FPU instruction_address (%X) -> A%d\r\n", FPU instruction_address, opcode & 7)); + m68k_areg (regs, opcode & 7) = FPU instruction_address; + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_fpcr_fpiar_2_Areg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ) { - D(bug("FMOVEM regs.fpcr (%X) -> A%d\r\n", regs.fpcr, opcode & 7)); - m68k_areg (regs, opcode & 7) = regs.fpcr; - D(bug("FMOVEM regs.fpiar (%X) -> A%d\r\n", regs.fpiar, opcode & 7)); - m68k_areg (regs, opcode & 7) = regs.fpiar; - dump_fp_regs( "END "); + D(bug("FMOVEM regs.FPU fpcr (%X) -> A%d\r\n", get_fpcr(), opcode & 7)); + m68k_areg (regs, opcode & 7) = get_fpcr(); + D(bug("FMOVEM FPU instruction_address (%X) -> A%d\r\n", FPU instruction_address, opcode & 7)); + m68k_areg (regs, opcode & 7) = FPU instruction_address; + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_fpcr_fpsr_2_Areg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra ) { - D(bug("FMOVEM regs.fpcr (%X) -> A%d\r\n", regs.fpcr, opcode & 7)); - m68k_areg (regs, opcode & 7) = regs.fpcr; - to_fpsr(); - D(bug("FMOVEM regs.fpsr (%X) -> A%d\r\n", regs.fpsr, opcode & 7)); - m68k_areg (regs, opcode & 7) = regs.fpsr; - dump_fp_regs( "END "); + D(bug("FMOVEM regs.FPU fpcr (%X) -> A%d\r\n", get_fpcr(), opcode & 7)); + m68k_areg (regs, opcode & 7) = get_fpcr(); + D(bug("FMOVEM regs.FPU fpsr (%X) -> A%d\r\n", get_fpsr(), opcode & 7)); + m68k_areg (regs, opcode & 7) = get_fpsr(); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_fpcr_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ) { - D(bug("FMOVEM regs.fpcr (%X) -> A%d\r\n", regs.fpcr, opcode & 7)); - m68k_areg (regs, opcode & 7) = regs.fpcr; - to_fpsr(); - D(bug("FMOVEM regs.fpsr (%X) -> A%d\r\n", regs.fpsr, opcode & 7)); - m68k_areg (regs, opcode & 7) = regs.fpsr; - D(bug("FMOVEM regs.fpiar (%X) -> A%d\r\n", regs.fpiar, opcode & 7)); - m68k_areg (regs, opcode & 7) = regs.fpiar; - dump_fp_regs( "END "); + D(bug("FMOVEM regs.FPU fpcr (%X) -> A%d\r\n", get_fpcr(), opcode & 7)); + m68k_areg (regs, opcode & 7) = get_fpcr(); + D(bug("FMOVEM regs.FPU fpsr (%X) -> A%d\r\n", get_fpsr(), opcode & 7)); + m68k_areg (regs, opcode & 7) = get_fpsr(); + D(bug("FMOVEM FPU instruction_address (%X) -> A%d\r\n", FPU instruction_address, opcode & 7)); + m68k_areg (regs, opcode & 7) = FPU instruction_address; + dump_registers( "END "); } /* ---------------------------- Areg -> CONTROL REGS ---------------------------- */ -void REGPARAM2 fpuop_fmovem_Areg_2_none( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_none( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVEM A%d -> control(none)\r\n", opcode & 7)); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Areg_2_fpiar( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpiar( uae_u32 opcode, uae_u32 extra ) { - regs.fpiar = m68k_areg (regs, opcode & 7); - D(bug("FMOVEM A%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar)); - dump_fp_regs( "END "); + FPU instruction_address = m68k_areg (regs, opcode & 7); + D(bug("FMOVEM A%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Areg_2_fpsr( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr( uae_u32 opcode, uae_u32 extra ) { - regs.fpsr = m68k_areg (regs, opcode & 7); - from_fpsr(); - D(bug("FMOVEM A%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr)); - dump_fp_regs( "END "); + set_fpsr( m68k_areg (regs, opcode & 7) ); + D(bug("FMOVEM A%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Areg_2_fpsr_fpiar( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ) { - regs.fpsr = m68k_areg (regs, opcode & 7); - from_fpsr(); - D(bug("FMOVEM A%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr)); - regs.fpiar = m68k_areg (regs, opcode & 7); - D(bug("FMOVEM A%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar)); - dump_fp_regs( "END "); + set_fpsr( m68k_areg (regs, opcode & 7) ); + D(bug("FMOVEM A%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); + FPU instruction_address = m68k_areg (regs, opcode & 7); + D(bug("FMOVEM A%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Areg_2_fpcr( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr( uae_u32 opcode, uae_u32 extra ) { - regs.fpcr = m68k_areg (regs, opcode & 7); - set_host_fpu_control_word(); - D(bug("FMOVEM A%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr)); - dump_fp_regs( "END "); + set_fpcr( m68k_areg (regs, opcode & 7) ); + D(bug("FMOVEM A%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Areg_2_fpcr_fpiar( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra ) { - regs.fpcr = m68k_areg (regs, opcode & 7); - set_host_fpu_control_word(); - D(bug("FMOVEM A%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr)); - regs.fpiar = m68k_areg (regs, opcode & 7); - D(bug("FMOVEM A%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar)); - dump_fp_regs( "END "); + set_fpcr( m68k_areg (regs, opcode & 7) ); + D(bug("FMOVEM A%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); + FPU instruction_address = m68k_areg (regs, opcode & 7); + D(bug("FMOVEM A%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Areg_2_fpcr_fpsr( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra ) { - regs.fpcr = m68k_areg (regs, opcode & 7); - set_host_fpu_control_word(); - D(bug("FMOVEM A%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr)); - regs.fpsr = m68k_areg (regs, opcode & 7); - from_fpsr(); - D(bug("FMOVEM A%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr)); - dump_fp_regs( "END "); + set_fpcr( m68k_areg (regs, opcode & 7) ); + D(bug("FMOVEM A%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); + set_fpsr( m68k_areg (regs, opcode & 7) ); + D(bug("FMOVEM A%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Areg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ) { - regs.fpcr = m68k_areg (regs, opcode & 7); - set_host_fpu_control_word(); - D(bug("FMOVEM A%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr)); - regs.fpsr = m68k_areg (regs, opcode & 7); - from_fpsr(); - D(bug("FMOVEM A%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr)); - regs.fpiar = m68k_areg (regs, opcode & 7); - D(bug("FMOVEM A%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar)); - dump_fp_regs( "END "); + set_fpcr( m68k_areg (regs, opcode & 7) ); + D(bug("FMOVEM A%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); + set_fpsr( m68k_areg (regs, opcode & 7) ); + D(bug("FMOVEM A%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); + FPU instruction_address = m68k_areg (regs, opcode & 7); + D(bug("FMOVEM A%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); + dump_registers( "END "); } /* ---------------------------- CONTROL REGS -> --MEMORY---------------------------- */ -void REGPARAM2 fpuop_fmovem_none_2_Mem_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVEM Control regs (none) -> mem\r\n" )); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { ad -= 4; - put_long (ad, regs.fpiar); - D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad )); + put_long (ad, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad )); m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { ad -= 4; - to_fpsr(); - put_long (ad, regs.fpsr); - D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad )); + put_long (ad, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { ad -= 8; - to_fpsr(); - put_long (ad, regs.fpsr); - D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad )); - put_long (ad+4, regs.fpiar); - D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+4 )); + put_long (ad, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); + put_long (ad+4, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpcr_2_Mem_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { ad -= 4; - put_long (ad, regs.fpcr); - D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad )); + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpcr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { ad -= 8; - put_long (ad, regs.fpcr); - D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad )); - put_long (ad+4, regs.fpiar); - D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+4 )); + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpcr_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { ad -= 8; - put_long (ad, regs.fpcr); - D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad )); - to_fpsr(); - put_long (ad+4, regs.fpsr); - D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad+4 )); + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { ad -= 12; - put_long (ad, regs.fpcr); - D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad )); - to_fpsr(); - put_long (ad+4, regs.fpsr); - D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad+4 )); - put_long (ad+8, regs.fpiar); - D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+8 )); + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); + put_long (ad+8, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+8 )); m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } /* ---------------------------- CONTROL REGS -> MEMORY++ ---------------------------- */ -void REGPARAM2 fpuop_fmovem_none_2_Mem_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVEM Control regs (none) -> mem\r\n" )); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - put_long (ad, regs.fpiar); - D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad )); + put_long (ad, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad )); m68k_areg (regs, opcode & 7) = ad+4; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - to_fpsr(); - put_long (ad, regs.fpsr); - D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad )); + put_long (ad, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); m68k_areg (regs, opcode & 7) = ad+4; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - to_fpsr(); - put_long (ad, regs.fpsr); - D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad )); - put_long (ad+4, regs.fpiar); - D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+4 )); + put_long (ad, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); + put_long (ad+4, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); m68k_areg (regs, opcode & 7) = ad+8; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpcr_2_Mem_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - put_long (ad, regs.fpcr); - D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad )); + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); m68k_areg (regs, opcode & 7) = ad+4; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpcr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - put_long (ad, regs.fpcr); - D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad )); - put_long (ad+4, regs.fpiar); - D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+4 )); + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); m68k_areg (regs, opcode & 7) = ad+8; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpcr_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) { - dump_fp_regs( "END "); + dump_registers( "END "); uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - put_long (ad, regs.fpcr); - D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad )); - to_fpsr(); - put_long (ad+4, regs.fpsr); - D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad+4 )); + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); m68k_areg (regs, opcode & 7) = ad+8; } } -void REGPARAM2 fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - put_long (ad, regs.fpcr); - D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad )); - to_fpsr(); - put_long (ad+4, regs.fpsr); - D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad+4 )); - put_long (ad+8, regs.fpiar); - D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+8 )); + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); + put_long (ad+8, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+8 )); m68k_areg (regs, opcode & 7) = ad+12; - dump_fp_regs( "END "); + dump_registers( "END "); } } /* ---------------------------- CONTROL REGS -> MEMORY ---------------------------- */ -void REGPARAM2 fpuop_fmovem_none_2_Mem( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVEM Control regs (none) -> mem\r\n" )); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_fpiar_2_Mem( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - put_long (ad, regs.fpiar); - D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad )); - dump_fp_regs( "END "); + put_long (ad, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad )); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpsr_2_Mem( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - to_fpsr(); - put_long (ad, regs.fpsr); - D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad )); - dump_fp_regs( "END "); + put_long (ad, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - to_fpsr(); - put_long (ad, regs.fpsr); - D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad )); - put_long (ad+4, regs.fpiar); - D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+4 )); - dump_fp_regs( "END "); + put_long (ad, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); + put_long (ad+4, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpcr_2_Mem( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - put_long (ad, regs.fpcr); - D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad )); - dump_fp_regs( "END "); + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - put_long (ad, regs.fpcr); - D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad )); - put_long (ad+4, regs.fpiar); - D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+4 )); - dump_fp_regs( "END "); + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - put_long (ad, regs.fpcr); - D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad )); - to_fpsr(); - put_long (ad+4, regs.fpsr); - D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad+4 )); - dump_fp_regs( "END "); + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - put_long (ad, regs.fpcr); - D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad )); - to_fpsr(); - put_long (ad+4, regs.fpsr); - D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad+4 )); - put_long (ad+8, regs.fpiar); - D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+8 )); - dump_fp_regs( "END "); + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); + put_long (ad+8, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+8 )); + dump_registers( "END "); } } /* ---------------------------- --MEMORY -> CONTROL REGS ---------------------------- */ -void REGPARAM2 fpuop_fmovem_Mem_2_none_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_predecrement( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVEM --Mem -> control(none)\r\n")); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Mem_2_fpiar_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { ad -= 4; - regs.fpiar = get_long (ad); - D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad, regs.fpiar )); + FPU instruction_address = get_long (ad); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad, FPU instruction_address )); m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpsr_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { ad -= 4; - regs.fpsr = get_long (ad); - from_fpsr(); - D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad, regs.fpsr )); + set_fpsr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { ad -= 8; - regs.fpsr = get_long (ad); - from_fpsr(); - D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad, regs.fpsr )); - regs.fpiar = get_long (ad+4); - D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+4, regs.fpiar )); + set_fpsr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); + FPU instruction_address = get_long (ad+4); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { ad -= 4; - regs.fpcr = get_long (ad); - set_host_fpu_control_word(); - D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr )); + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpiar_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { ad -= 8; - regs.fpcr = get_long (ad); - set_host_fpu_control_word(); - D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr )); - regs.fpiar = get_long (ad+4); - D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+4, regs.fpiar )); + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + FPU instruction_address = get_long (ad+4); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpsr_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { ad -= 8; - regs.fpcr = get_long (ad); - set_host_fpu_control_word(); - D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr )); - regs.fpsr = get_long (ad+4); - from_fpsr(); - D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad+4, regs.fpsr )); + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + set_fpsr( get_long (ad+4) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { ad -= 12; - regs.fpcr = get_long (ad); - set_host_fpu_control_word(); - D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr )); - regs.fpsr = get_long (ad+4); - from_fpsr(); - D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad+4, regs.fpsr )); - regs.fpiar = get_long (ad+8); - D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+8, regs.fpiar )); + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + set_fpsr( get_long (ad+4) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); + FPU instruction_address = get_long (ad+8); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+8, FPU instruction_address )); m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } /* ---------------------------- CONTROL REGS -> MEMORY++ ---------------------------- */ -void REGPARAM2 fpuop_fmovem_Mem_2_none_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_postincrement( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVEM Mem++ -> control(none)\r\n")); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Mem_2_fpiar_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - regs.fpiar = get_long (ad); - D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad, regs.fpiar )); + FPU instruction_address = get_long (ad); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad, FPU instruction_address )); m68k_areg (regs, opcode & 7) = ad+4; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpsr_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - regs.fpsr = get_long (ad); - from_fpsr(); - D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad, regs.fpsr )); + set_fpsr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); m68k_areg (regs, opcode & 7) = ad+4; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - regs.fpsr = get_long (ad); - from_fpsr(); - D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad, regs.fpsr )); - regs.fpiar = get_long (ad+4); - D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+4, regs.fpiar )); + set_fpsr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); + FPU instruction_address = get_long (ad+4); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); m68k_areg (regs, opcode & 7) = ad+8; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - regs.fpcr = get_long (ad); - set_host_fpu_control_word(); - D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr )); + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); m68k_areg (regs, opcode & 7) = ad+4; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpiar_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - regs.fpcr = get_long (ad); - set_host_fpu_control_word(); - D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr )); - regs.fpiar = get_long (ad+4); - D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+4, regs.fpiar )); + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + FPU instruction_address = get_long (ad+4); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); m68k_areg (regs, opcode & 7) = ad+8; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpsr_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - regs.fpcr = get_long (ad); - set_host_fpu_control_word(); - D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr )); - regs.fpsr = get_long (ad+4); - from_fpsr(); - D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad+4, regs.fpsr )); + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + set_fpsr( get_long (ad+4) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); m68k_areg (regs, opcode & 7) = ad+8; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - regs.fpcr = get_long (ad); - set_host_fpu_control_word(); - D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr )); - regs.fpsr = get_long (ad+4); - from_fpsr(); - D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad+4, regs.fpsr )); - regs.fpiar = get_long (ad+8); - D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+8, regs.fpiar )); + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + set_fpsr( get_long (ad+4) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); + FPU instruction_address = get_long (ad+8); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+8, FPU instruction_address )); m68k_areg (regs, opcode & 7) = ad+12; - dump_fp_regs( "END "); + dump_registers( "END "); } } @@ -3939,157 +3795,141 @@ void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement( uae_u32 opcode, /* ---------------------------- and ---------------------------- */ /* ---------------------------- IMMEDIATE -> CONTROL REGS ---------------------------- */ -void REGPARAM2 fpuop_fmovem_Mem_2_none_2_Mem( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_2_Mem( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVEM Mem -> control(none)\r\n")); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Mem_2_fpiar_2_Mem( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) { if ((opcode & 0x3f) == 0x3c) { - regs.fpiar = next_ilong(); - D(bug("FMOVEM #<%X> -> regs.fpiar\r\n", regs.fpiar)); + FPU instruction_address = next_ilong(); + D(bug("FMOVEM #<%X> -> FPU instruction_address\r\n", FPU instruction_address)); } else { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - regs.fpiar = get_long (ad); - D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad, regs.fpiar )); + FPU instruction_address = get_long (ad); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad, FPU instruction_address )); } } - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Mem_2_fpsr_2_Mem( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ) { if ((opcode & 0x3f) == 0x3c) { - regs.fpsr = next_ilong(); - from_fpsr(); - D(bug("FMOVEM #<%X> -> regs.fpsr\r\n", regs.fpsr)); + set_fpsr( next_ilong() ); + D(bug("FMOVEM #<%X> -> regs.FPU fpsr\r\n", get_fpsr())); } else { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - regs.fpsr = get_long (ad); - from_fpsr(); - D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad, regs.fpsr )); + set_fpsr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); } } - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Mem_2_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) { if ((opcode & 0x3f) == 0x3c) { - regs.fpsr = next_ilong(); - from_fpsr(); - D(bug("FMOVEM #<%X> -> regs.fpsr\r\n", regs.fpsr)); - regs.fpiar = next_ilong(); - D(bug("FMOVEM #<%X> -> regs.fpiar\r\n", regs.fpiar)); + set_fpsr( next_ilong() ); + D(bug("FMOVEM #<%X> -> regs.FPU fpsr\r\n", get_fpsr())); + FPU instruction_address = next_ilong(); + D(bug("FMOVEM #<%X> -> FPU instruction_address\r\n", FPU instruction_address)); } else { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - regs.fpsr = get_long (ad); - from_fpsr(); - D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad, regs.fpsr )); - regs.fpiar = get_long (ad+4); - D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+4, regs.fpiar )); + set_fpsr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); + FPU instruction_address = get_long (ad+4); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); } } - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_2_Mem( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra ) { if ((opcode & 0x3f) == 0x3c) { - regs.fpcr = next_ilong(); - set_host_fpu_control_word(); - D(bug("FMOVEM #<%X> -> regs.fpcr\r\n", regs.fpcr)); + set_fpcr( next_ilong() ); + D(bug("FMOVEM #<%X> -> regs.FPU fpcr\r\n", get_fpcr())); } else { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - regs.fpcr = get_long (ad); - set_host_fpu_control_word(); - D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr )); + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); } } - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) { if ((opcode & 0x3f) == 0x3c) { - regs.fpcr = next_ilong(); - set_host_fpu_control_word(); - D(bug("FMOVEM #<%X> -> regs.fpcr\r\n", regs.fpcr)); - regs.fpiar = next_ilong(); - D(bug("FMOVEM #<%X> -> regs.fpiar\r\n", regs.fpiar)); + set_fpcr( next_ilong() ); + D(bug("FMOVEM #<%X> -> regs.FPU fpcr\r\n", get_fpcr())); + FPU instruction_address = next_ilong(); + D(bug("FMOVEM #<%X> -> FPU instruction_address\r\n", FPU instruction_address)); } else { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - regs.fpcr = get_long (ad); - set_host_fpu_control_word(); - D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr )); - regs.fpiar = get_long (ad+4); - D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+4, regs.fpiar )); + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + FPU instruction_address = get_long (ad+4); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); } } - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ) { if ((opcode & 0x3f) == 0x3c) { - regs.fpcr = next_ilong(); - set_host_fpu_control_word(); - D(bug("FMOVEM #<%X> -> regs.fpcr\r\n", regs.fpcr)); - regs.fpsr = next_ilong(); - from_fpsr(); - D(bug("FMOVEM #<%X> -> regs.fpsr\r\n", regs.fpsr)); + set_fpcr( next_ilong() ); + D(bug("FMOVEM #<%X> -> regs.FPU fpcr\r\n", get_fpcr())); + set_fpsr( next_ilong() ); + D(bug("FMOVEM #<%X> -> regs.FPU fpsr\r\n", get_fpsr())); } else { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - regs.fpcr = get_long (ad); - set_host_fpu_control_word(); - D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr )); - regs.fpsr = get_long (ad+4); - from_fpsr(); - D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad+4, regs.fpsr )); + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + set_fpsr( get_long (ad+4) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); } } - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) { if ((opcode & 0x3f) == 0x3c) { - regs.fpcr = next_ilong(); - set_host_fpu_control_word(); - D(bug("FMOVEM #<%X> -> regs.fpcr\r\n", regs.fpcr)); - regs.fpsr = next_ilong(); - from_fpsr(); - D(bug("FMOVEM #<%X> -> regs.fpsr\r\n", regs.fpsr)); - regs.fpiar = next_ilong(); - D(bug("FMOVEM #<%X> -> regs.fpiar\r\n", regs.fpiar)); + set_fpcr( next_ilong() ); + D(bug("FMOVEM #<%X> -> regs.FPU fpcr\r\n", get_fpcr())); + set_fpsr( next_ilong() ); + D(bug("FMOVEM #<%X> -> regs.FPU fpsr\r\n", get_fpsr())); + FPU instruction_address = next_ilong(); + D(bug("FMOVEM #<%X> -> FPU instruction_address\r\n", FPU instruction_address)); } else { uae_u32 ad; if (get_fp_ad(opcode, &ad)) { - regs.fpcr = get_long (ad); - set_host_fpu_control_word(); - D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr )); - regs.fpsr = get_long (ad+4); - from_fpsr(); - D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad+4, regs.fpsr )); - regs.fpiar = get_long (ad+8); - D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+8, regs.fpiar )); + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + set_fpsr( get_long (ad+4) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); + FPU instruction_address = get_long (ad+8); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+8, FPU instruction_address )); } } - dump_fp_regs( "END "); + dump_registers( "END "); } /* ---------------------------- FMOVEM MEMORY -> FPP ---------------------------- */ -void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_pred_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = extra & 0xff; D(bug("FMOVEM memory->FPP\r\n")); @@ -4103,16 +3943,16 @@ void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_pred_postincrement( uae_u32 opcode, wrd2 = get_long (ad); ad -= 4; wrd1 = get_long (ad); - to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); } list <<= 1; } m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_pred_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = extra & 0xff; D(bug("FMOVEM memory->FPP\r\n")); @@ -4126,16 +3966,16 @@ void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_pred_predecrement( uae_u32 opcode, wrd2 = get_long (ad); ad -= 4; wrd1 = get_long (ad); - to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); } list <<= 1; } m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_pred( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = extra & 0xff; D(bug("FMOVEM memory->FPP\r\n")); @@ -4149,15 +3989,15 @@ void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_pred( uae_u32 opcode, uae_u16 extra wrd2 = get_long (ad); ad -= 4; wrd1 = get_long (ad); - to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); } list <<= 1; } - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_pred_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; D(bug("FMOVEM memory->FPP\r\n")); @@ -4171,16 +4011,16 @@ void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_pred_postincrement( uae_u32 opcode wrd2 = get_long (ad); ad -= 4; wrd1 = get_long (ad); - to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); } list <<= 1; } m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_pred_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; D(bug("FMOVEM memory->FPP\r\n")); @@ -4194,16 +4034,16 @@ void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_pred_predecrement( uae_u32 opcode, wrd2 = get_long (ad); ad -= 4; wrd1 = get_long (ad); - to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); } list <<= 1; } m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_pred( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; D(bug("FMOVEM memory->FPP\r\n")); @@ -4217,15 +4057,15 @@ void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_pred( uae_u32 opcode, uae_u16 extr wrd2 = get_long (ad); ad -= 4; wrd1 = get_long (ad); - to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); } list <<= 1; } - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_postinc_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = extra & 0xff; D(bug("FMOVEM memory->FPP\r\n")); @@ -4239,16 +4079,16 @@ void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_postinc_postincrement( uae_u32 opco ad += 4; wrd3 = get_long (ad); ad += 4; - to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); } list <<= 1; } m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_postinc_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = extra & 0xff; D(bug("FMOVEM memory->FPP\r\n")); @@ -4262,16 +4102,16 @@ void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_postinc_predecrement( uae_u32 opcod ad += 4; wrd3 = get_long (ad); ad += 4; - to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); } list <<= 1; } m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_postinc( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = extra & 0xff; D(bug("FMOVEM memory->FPP\r\n")); @@ -4285,15 +4125,15 @@ void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_postinc( uae_u32 opcode, uae_u16 ex ad += 4; wrd3 = get_long (ad); ad += 4; - to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); } list <<= 1; } - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_postinc_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; D(bug("FMOVEM memory->FPP\r\n")); @@ -4307,16 +4147,16 @@ void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_postinc_postincrement( uae_u32 opc ad += 4; wrd3 = get_long (ad); ad += 4; - to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); } list <<= 1; } m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_postinc_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; D(bug("FMOVEM memory->FPP\r\n")); @@ -4330,16 +4170,16 @@ void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_postinc_predecrement( uae_u32 opco ad += 4; wrd3 = get_long (ad); ad += 4; - to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); } list <<= 1; } m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_postinc( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; D(bug("FMOVEM memory->FPP\r\n")); @@ -4353,18 +4193,18 @@ void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_postinc( uae_u32 opcode, uae_u16 e ad += 4; wrd3 = get_long (ad); ad += 4; - to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); } list <<= 1; } - dump_fp_regs( "END "); + dump_registers( "END "); } } /* ---------------------------- FPP -> FMOVEM MEMORY ---------------------------- */ -void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_pred_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = extra & 0xff; D(bug("FMOVEM FPP->memory\r\n")); @@ -4372,7 +4212,7 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_pred_postincrement( uae_u32 opcode, for( int reg=7; reg>=0; reg-- ) { uae_u32 wrd1, wrd2, wrd3; if( list & 0x80 ) { - from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3); + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); ad -= 4; put_long (ad, wrd3); ad -= 4; @@ -4383,10 +4223,10 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_pred_postincrement( uae_u32 opcode, list <<= 1; } m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_pred_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = extra & 0xff; D(bug("FMOVEM FPP->memory\r\n")); @@ -4394,7 +4234,7 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_pred_predecrement( uae_u32 opcode, for( int reg=7; reg>=0; reg-- ) { uae_u32 wrd1, wrd2, wrd3; if( list & 0x80 ) { - from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3); + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); ad -= 4; put_long (ad, wrd3); ad -= 4; @@ -4405,10 +4245,10 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_pred_predecrement( uae_u32 opcode, list <<= 1; } m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_pred( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = extra & 0xff; D(bug("FMOVEM FPP->memory\r\n")); @@ -4416,7 +4256,7 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_pred( uae_u32 opcode, uae_u16 extra for( int reg=7; reg>=0; reg-- ) { uae_u32 wrd1, wrd2, wrd3; if( list & 0x80 ) { - from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3); + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); ad -= 4; put_long (ad, wrd3); ad -= 4; @@ -4426,10 +4266,10 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_pred( uae_u32 opcode, uae_u16 extra } list <<= 1; } - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; D(bug("FMOVEM FPP->memory\r\n")); @@ -4437,7 +4277,7 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement( uae_u32 opcode for( int reg=7; reg>=0; reg-- ) { uae_u32 wrd1, wrd2, wrd3; if( list & 0x80 ) { - from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3); + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); ad -= 4; put_long (ad, wrd3); ad -= 4; @@ -4448,10 +4288,10 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement( uae_u32 opcode list <<= 1; } m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; D(bug("FMOVEM FPP->memory\r\n")); @@ -4459,7 +4299,7 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement( uae_u32 opcode, for( int reg=7; reg>=0; reg-- ) { uae_u32 wrd1, wrd2, wrd3; if( list & 0x80 ) { - from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3); + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); ad -= 4; put_long (ad, wrd3); ad -= 4; @@ -4470,10 +4310,10 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement( uae_u32 opcode, list <<= 1; } m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_pred( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; D(bug("FMOVEM FPP->memory\r\n")); @@ -4481,7 +4321,7 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_pred( uae_u32 opcode, uae_u16 extr for( int reg=7; reg>=0; reg-- ) { uae_u32 wrd1, wrd2, wrd3; if( list & 0x80 ) { - from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3); + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); ad -= 4; put_long (ad, wrd3); ad -= 4; @@ -4491,10 +4331,10 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_pred( uae_u32 opcode, uae_u16 extr } list <<= 1; } - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = extra & 0xff; D(bug("FMOVEM FPP->memory\r\n")); @@ -4502,7 +4342,7 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement( uae_u32 opco for( int reg=0; reg<8; reg++ ) { uae_u32 wrd1, wrd2, wrd3; if( list & 0x80 ) { - from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3); + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); put_long (ad, wrd1); ad += 4; put_long (ad, wrd2); @@ -4513,10 +4353,10 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement( uae_u32 opco list <<= 1; } m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = extra & 0xff; D(bug("FMOVEM FPP->memory\r\n")); @@ -4524,7 +4364,7 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement( uae_u32 opcod for( int reg=0; reg<8; reg++ ) { uae_u32 wrd1, wrd2, wrd3; if( list & 0x80 ) { - from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3); + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); put_long (ad, wrd1); ad += 4; put_long (ad, wrd2); @@ -4535,10 +4375,10 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement( uae_u32 opcod list <<= 1; } m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_postinc( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = extra & 0xff; D(bug("FMOVEM FPP->memory\r\n")); @@ -4546,7 +4386,7 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_postinc( uae_u32 opcode, uae_u16 ex for( int reg=0; reg<8; reg++ ) { uae_u32 wrd1, wrd2, wrd3; if( list & 0x80 ) { - from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3); + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); put_long (ad, wrd1); ad += 4; put_long (ad, wrd2); @@ -4556,10 +4396,10 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_postinc( uae_u32 opcode, uae_u16 ex } list <<= 1; } - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; D(bug("FMOVEM FPP->memory\r\n")); @@ -4567,7 +4407,7 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement( uae_u32 opc for( int reg=0; reg<8; reg++ ) { uae_u32 wrd1, wrd2, wrd3; if( list & 0x80 ) { - from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3); + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); put_long (ad, wrd1); ad += 4; put_long (ad, wrd2); @@ -4578,10 +4418,10 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement( uae_u32 opc list <<= 1; } m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; D(bug("FMOVEM FPP->memory\r\n")); @@ -4589,7 +4429,7 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement( uae_u32 opco for( int reg=0; reg<8; reg++ ) { uae_u32 wrd1, wrd2, wrd3; if( list & 0x80 ) { - from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3); + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); put_long (ad, wrd1); ad += 4; put_long (ad, wrd2); @@ -4600,10 +4440,10 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement( uae_u32 opco list <<= 1; } m68k_areg (regs, opcode & 7) = ad; - dump_fp_regs( "END "); + dump_registers( "END "); } } -void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_postinc( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc( uae_u32 opcode, uae_u32 extra ) { uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; D(bug("FMOVEM FPP->memory\r\n")); @@ -4611,7 +4451,7 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_postinc( uae_u32 opcode, uae_u16 e for( int reg=0; reg<8; reg++ ) { uae_u32 wrd1, wrd2, wrd3; if( list & 0x80 ) { - from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3); + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); put_long (ad, wrd1); ad += 4; put_long (ad, wrd2); @@ -4621,869 +4461,861 @@ void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_postinc( uae_u32 opcode, uae_u16 e } list <<= 1; } - dump_fp_regs( "END "); + dump_registers( "END "); } } /* ---------------------------- FMOVEM CONSTANT ROM -> FPP ---------------------------- */ -void REGPARAM2 fpuop_do_fldpi( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fldpi( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: Pi\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_pi, sizeof(float80_s) ); - sw = SW_FINITE | INEX2; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_pi, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fldlg2( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fldlg2( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: Log 10 (2)\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_lg2, sizeof(float80_s) ); - sw = SW_FINITE | INEX2; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_lg2, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_load_const_e( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_e( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: e\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_e, sizeof(float80_s) ); - sw = SW_FINITE | INEX2; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_e, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fldl2e( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fldl2e( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: Log 2 (e)\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_l2e, sizeof(float80_s) ); - sw = SW_FINITE | INEX2; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_l2e, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_load_const_log_10_e( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_log_10_e( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: Log 10 (e)\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_log_10_e, sizeof(float80_s) ); - sw = SW_FINITE | INEX2; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_log_10_e, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fldz( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fldz( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: zero\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_z, sizeof(float80_s) ); - sw = SW_Z; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_z, sizeof(fpu_register) ); + x86_status_word = SW_Z; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fldln2( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fldln2( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: ln(2)\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_ln2, sizeof(float80_s) ); - sw = SW_FINITE | INEX2; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_ln2, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_load_const_ln_10( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_ln_10( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: ln(10)\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_ln_10, sizeof(float80_s) ); - sw = SW_FINITE | INEX2; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_ln_10, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fld1( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fld1( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: 1.0e0\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_1, sizeof(float80_s) ); - sw = SW_FINITE; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_1, sizeof(fpu_register) ); + x86_status_word = SW_FINITE; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_load_const_1e1( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: 1.0e1\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_1e1, sizeof(float80_s) ); - sw = SW_FINITE; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e1, sizeof(fpu_register) ); + x86_status_word = SW_FINITE; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_load_const_1e2( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: 1.0e2\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_1e2, sizeof(float80_s) ); - sw = SW_FINITE; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e2, sizeof(fpu_register) ); + x86_status_word = SW_FINITE; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_load_const_1e4( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: 1.0e4\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_1e4, sizeof(float80_s) ); - sw = SW_FINITE; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e4, sizeof(fpu_register) ); + x86_status_word = SW_FINITE; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_load_const_1e8( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e8( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: 1.0e8\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_1e8, sizeof(float80_s) ); - sw = SW_FINITE | INEX2; // Is it really INEX2? - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e8, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; // Is it really FPSR_EXCEPTION_INEX2? + dump_registers( "END "); } -void REGPARAM2 fpuop_do_load_const_1e16( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e16( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: 1.0e16\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_1e16, sizeof(float80_s) ); - sw = SW_FINITE | INEX2; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e16, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_load_const_1e32( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e32( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: 1.0e32\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_1e32, sizeof(float80_s) ); - sw = SW_FINITE | INEX2; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e32, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_load_const_1e64( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e64( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: 1.0e64\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_1e64, sizeof(float80_s) ); - sw = SW_FINITE | INEX2; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e64, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_load_const_1e128( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e128( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: 1.0e128\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_1e128, sizeof(float80_s) ); - sw = SW_FINITE | INEX2; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e128, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_load_const_1e256( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e256( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: 1.0e256\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_1e256, sizeof(float80_s) ); - sw = SW_FINITE | INEX2; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e256, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_load_const_1e512( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e512( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: 1.0e512\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_1e512, sizeof(float80_s) ); - sw = SW_FINITE | INEX2; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e512, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_load_const_1e1024( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1024( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: 1.0e1024\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_1e1024, sizeof(float80_s) ); - sw = SW_FINITE | INEX2; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e1024, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_load_const_1e2048( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2048( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: 1.0e2048\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_1e2048, sizeof(float80_s) ); - sw = SW_FINITE | INEX2; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e2048, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); } -void REGPARAM2 fpuop_do_load_const_1e4096( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4096( uae_u32 opcode, uae_u32 extra ) { D(bug("FMOVECR memory->FPP FP const: 1.0e4096\r\n")); - memcpy( fp_reg[(extra>>7) & 7], const_1e4096, sizeof(float80_s) ); - sw = SW_FINITE | INEX2; - dump_fp_regs( "END "); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e4096, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); } /* ---------------------------- ALU ---------------------------- */ -void REGPARAM2 fpuop_do_fmove( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fmove( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FMOVE %s\r\n",etos(src))); - do_fmove( fp_reg[reg], src ); + do_fmove( FPU registers[reg], src ); build_ex_status(); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fint( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fint( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FINT %s, opcode=%X, extra=%X, ta %X\r\n",etos(src),opcode,extra,m68k_getpc())); - do_fint( fp_reg[reg], src ); - dump_fp_regs( "END "); + do_fint( FPU registers[reg], src ); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fsinh( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fsinh( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FSINH %s\r\n",etos(src))); - do_fsinh( fp_reg[reg], src ); + do_fsinh( FPU registers[reg], src ); build_ex_status(); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fintrz( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fintrz( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FINTRZ %s\r\n",etos(src))); - do_fintrz( fp_reg[reg], src ); - dump_fp_regs( "END "); + do_fintrz( FPU registers[reg], src ); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fsqrt( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fsqrt( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FSQRT %s\r\n",etos(src))); - do_fsqrt( fp_reg[reg], src ); - dump_fp_regs( "END "); + do_fsqrt( FPU registers[reg], src ); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_flognp1( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_flognp1( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FLOGNP1 %s\r\n",etos(src))); - do_flognp1( fp_reg[reg], src ); + do_flognp1( FPU registers[reg], src ); build_ex_status(); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fetoxm1( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fetoxm1( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FETOXM1 %s\r\n",etos(src))); - do_fetoxm1( fp_reg[reg], src ); + do_fetoxm1( FPU registers[reg], src ); build_ex_status(); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_ftanh( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_ftanh( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FTANH %s\r\n",etos(src))); - do_ftanh( fp_reg[reg], src ); + do_ftanh( FPU registers[reg], src ); build_ex_status(); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fatan( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fatan( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FATAN %s\r\n",etos(src))); - do_fatan( fp_reg[reg], src ); + do_fatan( FPU registers[reg], src ); build_ex_status(); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fasin( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fasin( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FASIN %s\r\n",etos(src))); - do_fasin( fp_reg[reg], src ); + do_fasin( FPU registers[reg], src ); build_ex_status(); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fatanh( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fatanh( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FATANH %s\r\n",etos(src))); - do_fatanh( fp_reg[reg], src ); + do_fatanh( FPU registers[reg], src ); build_ex_status(); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fsin( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fsin( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FSIN %s\r\n",etos(src))); - do_fsin( fp_reg[reg], src ); - dump_fp_regs( "END "); + do_fsin( FPU registers[reg], src ); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_ftan( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_ftan( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FTAN %s\r\n",etos(src))); - do_ftan( fp_reg[reg], src ); - dump_fp_regs( "END "); + do_ftan( FPU registers[reg], src ); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fetox( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fetox( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FETOX %s\r\n",etos(src))); - do_fetox( fp_reg[reg], src ); + do_fetox( FPU registers[reg], src ); build_ex_status(); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_ftwotox( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_ftwotox( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FTWOTOX %s\r\n",etos(src))); - do_ftwotox( fp_reg[reg], src ); + do_ftwotox( FPU registers[reg], src ); build_ex_status(); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_ftentox( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_ftentox( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FTENTOX %s\r\n",etos(src))); - do_ftentox( fp_reg[reg], src ); + do_ftentox( FPU registers[reg], src ); build_ex_status(); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_flogn( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_flogn( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FLOGN %s\r\n",etos(src))); - do_flogn( fp_reg[reg], src ); + do_flogn( FPU registers[reg], src ); build_ex_status(); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_flog10( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_flog10( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FLOG10 %s\r\n",etos(src))); - do_flog10( fp_reg[reg], src ); + do_flog10( FPU registers[reg], src ); build_ex_status(); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_flog2( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_flog2( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FLOG2 %s\r\n",etos(src))); - do_flog2( fp_reg[reg], src ); + do_flog2( FPU registers[reg], src ); build_ex_status(); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fabs( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fabs( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FABS %s\r\n",etos(src))); - do_fabs( fp_reg[reg], src ); - dump_fp_regs( "END "); + do_fabs( FPU registers[reg], src ); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fcosh( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fcosh( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FCOSH %s\r\n",etos(src))); - do_fcosh( fp_reg[reg], src ); + do_fcosh( FPU registers[reg], src ); build_ex_status(); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fneg( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fneg( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FNEG %s\r\n",etos(src))); - do_fneg( fp_reg[reg], src ); - dump_fp_regs( "END "); + do_fneg( FPU registers[reg], src ); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_facos( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_facos( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FACOS %s\r\n",etos(src))); - do_facos( fp_reg[reg], src ); + do_facos( FPU registers[reg], src ); build_ex_status(); - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fcos( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fcos( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FCOS %s\r\n",etos(src))); - do_fcos( fp_reg[reg], src ); - dump_fp_regs( "END "); + do_fcos( FPU registers[reg], src ); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fgetexp( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fgetexp( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FGETEXP %s\r\n",etos(src))); if( IS_INFINITY(src) ) { - MAKE_NAN( fp_reg[reg] ); - do_ftst( fp_reg[reg] ); - sw |= SW_IE; + MAKE_NAN( FPU registers[reg] ); + do_ftst( FPU registers[reg] ); + x86_status_word |= SW_IE; } else { - do_fgetexp( fp_reg[reg], src ); + do_fgetexp( FPU registers[reg], src ); } - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fgetman( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fgetman( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FGETMAN %s\r\n",etos(src))); if( IS_INFINITY(src) ) { - MAKE_NAN( fp_reg[reg] ); - do_ftst( fp_reg[reg] ); - sw |= SW_IE; + MAKE_NAN( FPU registers[reg] ); + do_ftst( FPU registers[reg] ); + x86_status_word |= SW_IE; } else { - do_fgetman( fp_reg[reg], src ); + do_fgetman( FPU registers[reg], src ); } - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fdiv( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fdiv( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FDIV %s\r\n",etos(src))); - do_fdiv( fp_reg[reg], src ); - dump_fp_regs( "END "); + do_fdiv( FPU registers[reg], src ); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fmod( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fmod( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FMOD %s\r\n",etos(src))); #if USE_3_BIT_QUOTIENT - do_fmod( fp_reg[reg], src ); + do_fmod( FPU registers[reg], src ); #else - if( (cw & X86_ROUND_CONTROL_MASK) == CW_RC_ZERO ) { - do_fmod_dont_set_cw( fp_reg[reg], src ); + if( (x86_control_word & X86_ROUNDING_MODE) == CW_RC_ZERO ) { + do_fmod_dont_set_cw( FPU registers[reg], src ); } else { - do_fmod( fp_reg[reg], src ); + do_fmod( FPU registers[reg], src ); } #endif - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_frem( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_frem( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FREM %s\r\n",etos(src))); #if USE_3_BIT_QUOTIENT - do_frem( fp_reg[reg], src ); + do_frem( FPU registers[reg], src ); #else - if( (cw & X86_ROUND_CONTROL_MASK) == CW_RC_NEAR ) { - do_frem_dont_set_cw( fp_reg[reg], src ); + if( (x86_control_word & X86_ROUNDING_MODE) == CW_RC_NEAR ) { + do_frem_dont_set_cw( FPU registers[reg], src ); } else { - do_frem( fp_reg[reg], src ); + do_frem( FPU registers[reg], src ); } #endif - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fadd( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fadd( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FADD %s\r\n",etos(src))); - do_fadd( fp_reg[reg], src ); - dump_fp_regs( "END "); + do_fadd( FPU registers[reg], src ); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fmul( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fmul( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FMUL %s\r\n",etos(src))); - do_fmul( fp_reg[reg], src ); - dump_fp_regs( "END "); + do_fmul( FPU registers[reg], src ); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fsgldiv( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fsgldiv( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FSGLDIV %s\r\n",etos(src))); - do_fsgldiv( fp_reg[reg], src ); - dump_fp_regs( "END "); + do_fsgldiv( FPU registers[reg], src ); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fscale( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fscale( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FSCALE %s, opcode=%X, extra=%X, ta %X\r\n",etos(src),opcode,extra,m68k_getpc())); - if( IS_INFINITY(fp_reg[reg]) ) { - MAKE_NAN( fp_reg[reg] ); - do_ftst( fp_reg[reg] ); - sw |= SW_IE; + if( IS_INFINITY(FPU registers[reg]) ) { + MAKE_NAN( FPU registers[reg] ); + do_ftst( FPU registers[reg] ); + x86_status_word |= SW_IE; } else { // When the absolute value of the source operand is >= 2^14, // an overflow or underflow always results. - do_fscale( fp_reg[reg], src ); + do_fscale( FPU registers[reg], src ); } - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fsglmul( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fsglmul( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FSGLMUL %s\r\n",etos(src))); - do_fsglmul( fp_reg[reg], src ); - dump_fp_regs( "END "); + do_fsglmul( FPU registers[reg], src ); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fsub( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fsub( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FSUB %s\r\n",etos(src))); - do_fsub( fp_reg[reg], src ); - dump_fp_regs( "END "); + do_fsub( FPU registers[reg], src ); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fsincos( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fsincos( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FSINCOS %s\r\n",etos(src))); - do_fsincos( fp_reg[reg], fp_reg[extra & 7], src ); - dump_fp_regs( "END "); + do_fsincos( FPU registers[reg], FPU registers[extra & 7], src ); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_fcmp( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_fcmp( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FCMP %s\r\n",etos(src))); if( IS_INFINITY(src) ) { if( IS_NEGATIVE(src) ) { - if( IS_INFINITY(fp_reg[reg]) && IS_NEGATIVE(fp_reg[reg]) ) { - sw = SW_Z | SW_N; + if( IS_INFINITY(FPU registers[reg]) && IS_NEGATIVE(FPU registers[reg]) ) { + x86_status_word = SW_Z | SW_N; D(bug("-INF FCMP -INF -> NZ\r\n")); } else { - sw = SW_FINITE; + x86_status_word = SW_FINITE; D(bug("X FCMP -INF -> None\r\n")); } } else { - if( IS_INFINITY(fp_reg[reg]) && !IS_NEGATIVE(fp_reg[reg]) ) { - sw = SW_Z; + if( IS_INFINITY(FPU registers[reg]) && !IS_NEGATIVE(FPU registers[reg]) ) { + x86_status_word = SW_Z; D(bug("+INF FCMP +INF -> Z\r\n")); } else { - sw = SW_N; + x86_status_word = SW_N; D(bug("X FCMP +INF -> N\r\n")); } } - } else if( IS_INFINITY(fp_reg[reg]) ) { - if( IS_NEGATIVE(fp_reg[reg]) ) { - sw = SW_N; + } else if( IS_INFINITY(FPU registers[reg]) ) { + if( IS_NEGATIVE(FPU registers[reg]) ) { + x86_status_word = SW_N; D(bug("-INF FCMP X -> Negative\r\n")); } else { - sw = SW_FINITE; + x86_status_word = SW_FINITE; D(bug("+INF FCMP X -> None\r\n")); } } else { - do_fcmp( fp_reg[reg], src ); + do_fcmp( FPU registers[reg], src ); } - dump_fp_regs( "END "); + dump_registers( "END "); } -void REGPARAM2 fpuop_do_ftst( uae_u32 opcode, uae_u16 extra ) +PRIVATE void REGPARAM2 FFPU fpuop_do_ftst( uae_u32 opcode, uae_u32 extra ) { int reg = (extra >> 7) & 7; - float80_s src; + fpu_register src; if (get_fp_value (opcode, extra, src) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); - dump_fp_regs( "END "); + dump_registers( "END "); return; } D(bug("FTST %s\r\n",etos(src))); do_ftst( src ); build_ex_status(); - dump_fp_regs( "END "); + dump_registers( "END "); } -/* ---------------------------- SET FPU MODE ---------------------------- */ - -void fpu_set_integral_fpu( bool is_integral ) -{ - is_integral_68040_fpu = (uae_u32)is_integral; -} - - /* ---------------------------- SETUP TABLES ---------------------------- */ -static void build_fpp_opp_lookup_table() +PRIVATE void FFPU build_fpp_opp_lookup_table () { for( uae_u32 opcode=0; opcode<=0x38; opcode+=8 ) { for( uae_u32 extra=0; extra<65536; extra++ ) { uae_u32 mask = (extra & 0xFC7F) | ((opcode & 0x0038) << 4); - fpufunctbl[mask] = fpuop_illg; + fpufunctbl[mask] = & FFPU fpuop_illg; switch ((extra >> 13) & 0x7) { case 3: - fpufunctbl[mask] = fpuop_fmove_2_ea; + fpufunctbl[mask] = & FFPU fpuop_fmove_2_ea; break; case 4: case 5: @@ -5491,55 +5323,55 @@ static void build_fpp_opp_lookup_table() if (extra & 0x2000) { // dr bit switch( extra & 0x1C00 ) { case 0x0000: - fpufunctbl[mask] = fpuop_fmovem_none_2_Dreg; + fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Dreg; break; case 0x0400: - fpufunctbl[mask] = fpuop_fmovem_fpiar_2_Dreg; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Dreg; break; case 0x0800: - fpufunctbl[mask] = fpuop_fmovem_fpsr_2_Dreg; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Dreg; break; case 0x0C00: - fpufunctbl[mask] = fpuop_fmovem_fpsr_fpiar_2_Dreg; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Dreg; break; case 0x1000: - fpufunctbl[mask] = fpuop_fmovem_fpcr_2_Dreg; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Dreg; break; case 0x1400: - fpufunctbl[mask] = fpuop_fmovem_fpcr_fpiar_2_Dreg; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Dreg; break; case 0x1800: - fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_2_Dreg; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Dreg; break; case 0x1C00: - fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_fpiar_2_Dreg; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Dreg; break; } } else { switch( extra & 0x1C00 ) { case 0x0000: - fpufunctbl[mask] = fpuop_fmovem_Dreg_2_none; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_none; break; case 0x0400: - fpufunctbl[mask] = fpuop_fmovem_Dreg_2_fpiar; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpiar; break; case 0x0800: - fpufunctbl[mask] = fpuop_fmovem_Dreg_2_fpsr; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpsr; break; case 0x0C00: - fpufunctbl[mask] = fpuop_fmovem_Dreg_2_fpsr_fpiar; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpsr_fpiar; break; case 0x1000: - fpufunctbl[mask] = fpuop_fmovem_Dreg_2_fpcr; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpcr; break; case 0x1400: - fpufunctbl[mask] = fpuop_fmovem_Dreg_2_fpcr_fpiar; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpcr_fpiar; break; case 0x1800: - fpufunctbl[mask] = fpuop_fmovem_Dreg_2_fpcr_fpsr; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr; break; case 0x1C00: - fpufunctbl[mask] = fpuop_fmovem_Dreg_2_fpcr_fpsr_fpiar; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr_fpiar; break; } } @@ -5547,55 +5379,55 @@ static void build_fpp_opp_lookup_table() if (extra & 0x2000) { // dr bit switch( extra & 0x1C00 ) { case 0x0000: - fpufunctbl[mask] = fpuop_fmovem_none_2_Areg; + fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Areg; break; case 0x0400: - fpufunctbl[mask] = fpuop_fmovem_fpiar_2_Areg; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Areg; break; case 0x0800: - fpufunctbl[mask] = fpuop_fmovem_fpsr_2_Areg; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Areg; break; case 0x0C00: - fpufunctbl[mask] = fpuop_fmovem_fpsr_fpiar_2_Areg; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Areg; break; case 0x1000: - fpufunctbl[mask] = fpuop_fmovem_fpcr_2_Areg; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Areg; break; case 0x1400: - fpufunctbl[mask] = fpuop_fmovem_fpcr_fpiar_2_Areg; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Areg; break; case 0x1800: - fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_2_Areg; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Areg; break; case 0x1C00: - fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_fpiar_2_Areg; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Areg; break; } } else { switch( extra & 0x1C00 ) { case 0x0000: - fpufunctbl[mask] = fpuop_fmovem_Areg_2_none; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_none; break; case 0x0400: - fpufunctbl[mask] = fpuop_fmovem_Areg_2_fpiar; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpiar; break; case 0x0800: - fpufunctbl[mask] = fpuop_fmovem_Areg_2_fpsr; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpsr; break; case 0x0C00: - fpufunctbl[mask] = fpuop_fmovem_Areg_2_fpsr_fpiar; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpsr_fpiar; break; case 0x1000: - fpufunctbl[mask] = fpuop_fmovem_Areg_2_fpcr; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpcr; break; case 0x1400: - fpufunctbl[mask] = fpuop_fmovem_Areg_2_fpcr_fpiar; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpcr_fpiar; break; case 0x1800: - fpufunctbl[mask] = fpuop_fmovem_Areg_2_fpcr_fpsr; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpcr_fpsr; break; case 0x1C00: - fpufunctbl[mask] = fpuop_fmovem_Areg_2_fpcr_fpsr_fpiar; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpcr_fpsr_fpiar; break; } } @@ -5603,82 +5435,82 @@ static void build_fpp_opp_lookup_table() if ((opcode & 0x38) == 0x20) { switch( extra & 0x1C00 ) { case 0x0000: - fpufunctbl[mask] = fpuop_fmovem_none_2_Mem_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Mem_predecrement; break; case 0x0400: - fpufunctbl[mask] = fpuop_fmovem_fpiar_2_Mem_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Mem_predecrement; break; case 0x0800: - fpufunctbl[mask] = fpuop_fmovem_fpsr_2_Mem_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Mem_predecrement; break; case 0x0C00: - fpufunctbl[mask] = fpuop_fmovem_fpsr_fpiar_2_Mem_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_predecrement; break; case 0x1000: - fpufunctbl[mask] = fpuop_fmovem_fpcr_2_Mem_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Mem_predecrement; break; case 0x1400: - fpufunctbl[mask] = fpuop_fmovem_fpcr_fpiar_2_Mem_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_predecrement; break; case 0x1800: - fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_2_Mem_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_predecrement; break; case 0x1C00: - fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_predecrement; break; } } else if ((opcode & 0x38) == 0x18) { switch( extra & 0x1C00 ) { case 0x0000: - fpufunctbl[mask] = fpuop_fmovem_none_2_Mem_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Mem_postincrement; break; case 0x0400: - fpufunctbl[mask] = fpuop_fmovem_fpiar_2_Mem_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Mem_postincrement; break; case 0x0800: - fpufunctbl[mask] = fpuop_fmovem_fpsr_2_Mem_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Mem_postincrement; break; case 0x0C00: - fpufunctbl[mask] = fpuop_fmovem_fpsr_fpiar_2_Mem_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_postincrement; break; case 0x1000: - fpufunctbl[mask] = fpuop_fmovem_fpcr_2_Mem_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Mem_postincrement; break; case 0x1400: - fpufunctbl[mask] = fpuop_fmovem_fpcr_fpiar_2_Mem_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_postincrement; break; case 0x1800: - fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_2_Mem_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_postincrement; break; case 0x1C00: - fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_postincrement; break; } } else { switch( extra & 0x1C00 ) { case 0x0000: - fpufunctbl[mask] = fpuop_fmovem_none_2_Mem; + fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Mem; break; case 0x0400: - fpufunctbl[mask] = fpuop_fmovem_fpiar_2_Mem; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Mem; break; case 0x0800: - fpufunctbl[mask] = fpuop_fmovem_fpsr_2_Mem; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Mem; break; case 0x0C00: - fpufunctbl[mask] = fpuop_fmovem_fpsr_fpiar_2_Mem; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Mem; break; case 0x1000: - fpufunctbl[mask] = fpuop_fmovem_fpcr_2_Mem; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Mem; break; case 0x1400: - fpufunctbl[mask] = fpuop_fmovem_fpcr_fpiar_2_Mem; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Mem; break; case 0x1800: - fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_2_Mem; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Mem; break; case 0x1C00: - fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem; break; } } @@ -5686,82 +5518,82 @@ static void build_fpp_opp_lookup_table() if ((opcode & 0x38) == 0x20) { switch( extra & 0x1C00 ) { case 0x0000: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_none_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_none_predecrement; break; case 0x0400: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpiar_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpiar_predecrement; break; case 0x0800: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpsr_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_predecrement; break; case 0x0C00: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpsr_fpiar_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_predecrement; break; case 0x1000: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_predecrement; break; case 0x1400: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpiar_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_predecrement; break; case 0x1800: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpsr_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_predecrement; break; case 0x1C00: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_predecrement; break; } } else if ((opcode & 0x38) == 0x18) { switch( extra & 0x1C00 ) { case 0x0000: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_none_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_none_postincrement; break; case 0x0400: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpiar_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpiar_postincrement; break; case 0x0800: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpsr_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_postincrement; break; case 0x0C00: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpsr_fpiar_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_postincrement; break; case 0x1000: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_postincrement; break; case 0x1400: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpiar_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_postincrement; break; case 0x1800: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpsr_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_postincrement; break; case 0x1C00: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement; break; } } else { switch( extra & 0x1C00 ) { case 0x0000: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_none_2_Mem; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_none_2_Mem; break; case 0x0400: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpiar_2_Mem; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpiar_2_Mem; break; case 0x0800: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpsr_2_Mem; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_2_Mem; break; case 0x0C00: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpsr_fpiar_2_Mem; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_2_Mem; break; case 0x1000: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_2_Mem; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_2_Mem; break; case 0x1400: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpiar_2_Mem; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_2_Mem; break; case 0x1800: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpsr_2_Mem; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_2_Mem; break; case 0x1C00: - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_2_Mem; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_2_Mem; break; } } @@ -5770,35 +5602,35 @@ static void build_fpp_opp_lookup_table() switch ((extra >> 11) & 3) { case 0: /* static pred */ if ((opcode & 0x38) == 0x18) // post-increment? - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_static_pred_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_pred_postincrement; else if ((opcode & 0x38) == 0x20) // pre-decrement? - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_static_pred_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_pred_predecrement; else - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_static_pred; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_pred; break; case 1: /* dynamic pred */ if ((opcode & 0x38) == 0x18) // post-increment? - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_dynamic_pred_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_postincrement; else if ((opcode & 0x38) == 0x20) // pre-decrement? - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_dynamic_pred_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_predecrement; else - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_dynamic_pred; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred; break; case 2: /* static postinc */ if ((opcode & 0x38) == 0x18) // post-increment? - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_static_postinc_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_postincrement; else if ((opcode & 0x38) == 0x20) // pre-decrement? - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_static_postinc_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_predecrement; else - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_static_postinc; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_postinc; break; case 3: /* dynamic postinc */ if ((opcode & 0x38) == 0x18) // post-increment? - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_dynamic_postinc_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_postincrement; else if ((opcode & 0x38) == 0x20) // pre-decrement? - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_dynamic_postinc_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_predecrement; else - fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_dynamic_postinc; + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc; break; } break; @@ -5806,35 +5638,35 @@ static void build_fpp_opp_lookup_table() switch ((extra >> 11) & 3) { case 0: /* static pred */ if ((opcode & 0x38) == 0x18) // post-increment? - fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_static_pred_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_pred_postincrement; else if ((opcode & 0x38) == 0x20) // pre-decrement? - fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_static_pred_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_pred_predecrement; else - fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_static_pred; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_pred; break; case 1: /* dynamic pred */ if ((opcode & 0x38) == 0x18) // post-increment? - fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement; else if ((opcode & 0x38) == 0x20) // pre-decrement? - fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement; else - fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_dynamic_pred; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred; break; case 2: /* static postinc */ if ((opcode & 0x38) == 0x18) // post-increment? - fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement; else if ((opcode & 0x38) == 0x20) // pre-decrement? - fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement; else - fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_static_postinc; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_postinc; break; case 3: /* dynamic postinc */ if ((opcode & 0x38) == 0x18) // post-increment? - fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement; else if ((opcode & 0x38) == 0x20) // pre-decrement? - fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement; else - fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_dynamic_postinc; + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc; break; } break; @@ -5843,70 +5675,70 @@ static void build_fpp_opp_lookup_table() if ((extra & 0xfc00) == 0x5c00) { switch (extra & 0x7f) { case 0x00: - fpufunctbl[mask] = fpuop_do_fldpi; + fpufunctbl[mask] = & FFPU fpuop_do_fldpi; break; case 0x0b: - fpufunctbl[mask] = fpuop_do_fldlg2; + fpufunctbl[mask] = & FFPU fpuop_do_fldlg2; break; case 0x0c: - fpufunctbl[mask] = fpuop_do_load_const_e; + fpufunctbl[mask] = & FFPU fpuop_do_load_const_e; break; case 0x0d: - fpufunctbl[mask] = fpuop_do_fldl2e; + fpufunctbl[mask] = & FFPU fpuop_do_fldl2e; break; case 0x0e: - fpufunctbl[mask] = fpuop_do_load_const_log_10_e; + fpufunctbl[mask] = & FFPU fpuop_do_load_const_log_10_e; break; case 0x0f: - fpufunctbl[mask] = fpuop_do_fldz; + fpufunctbl[mask] = & FFPU fpuop_do_fldz; break; case 0x30: - fpufunctbl[mask] = fpuop_do_fldln2; + fpufunctbl[mask] = & FFPU fpuop_do_fldln2; break; case 0x31: - fpufunctbl[mask] = fpuop_do_load_const_ln_10; + fpufunctbl[mask] = & FFPU fpuop_do_load_const_ln_10; break; case 0x32: - fpufunctbl[mask] = fpuop_do_fld1; + fpufunctbl[mask] = & FFPU fpuop_do_fld1; break; case 0x33: - fpufunctbl[mask] = fpuop_do_load_const_1e1; + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e1; break; case 0x34: - fpufunctbl[mask] = fpuop_do_load_const_1e2; + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e2; break; case 0x35: - fpufunctbl[mask] = fpuop_do_load_const_1e4; + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e4; break; case 0x36: - fpufunctbl[mask] = fpuop_do_load_const_1e8; + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e8; break; case 0x37: - fpufunctbl[mask] = fpuop_do_load_const_1e16; + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e16; break; case 0x38: - fpufunctbl[mask] = fpuop_do_load_const_1e32; + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e32; break; case 0x39: - fpufunctbl[mask] = fpuop_do_load_const_1e64; + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e64; break; case 0x3a: - fpufunctbl[mask] = fpuop_do_load_const_1e128; + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e128; break; case 0x3b: - fpufunctbl[mask] = fpuop_do_load_const_1e256; + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e256; break; case 0x3c: - fpufunctbl[mask] = fpuop_do_load_const_1e512; + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e512; break; case 0x3d: - fpufunctbl[mask] = fpuop_do_load_const_1e1024; + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e1024; break; case 0x3e: - fpufunctbl[mask] = fpuop_do_load_const_1e2048; + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e2048; break; case 0x3f: - fpufunctbl[mask] = fpuop_do_load_const_1e4096; + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e4096; break; } break; @@ -5914,109 +5746,109 @@ static void build_fpp_opp_lookup_table() switch (extra & 0x7f) { case 0x00: - fpufunctbl[mask] = fpuop_do_fmove; + fpufunctbl[mask] = & FFPU fpuop_do_fmove; break; case 0x01: - fpufunctbl[mask] = fpuop_do_fint; + fpufunctbl[mask] = & FFPU fpuop_do_fint; break; case 0x02: - fpufunctbl[mask] = fpuop_do_fsinh; + fpufunctbl[mask] = & FFPU fpuop_do_fsinh; break; case 0x03: - fpufunctbl[mask] = fpuop_do_fintrz; + fpufunctbl[mask] = & FFPU fpuop_do_fintrz; break; case 0x04: - fpufunctbl[mask] = fpuop_do_fsqrt; + fpufunctbl[mask] = & FFPU fpuop_do_fsqrt; break; case 0x06: - fpufunctbl[mask] = fpuop_do_flognp1; + fpufunctbl[mask] = & FFPU fpuop_do_flognp1; break; case 0x08: - fpufunctbl[mask] = fpuop_do_fetoxm1; + fpufunctbl[mask] = & FFPU fpuop_do_fetoxm1; break; case 0x09: - fpufunctbl[mask] = fpuop_do_ftanh; + fpufunctbl[mask] = & FFPU fpuop_do_ftanh; break; case 0x0a: - fpufunctbl[mask] = fpuop_do_fatan; + fpufunctbl[mask] = & FFPU fpuop_do_fatan; break; case 0x0c: - fpufunctbl[mask] = fpuop_do_fasin; + fpufunctbl[mask] = & FFPU fpuop_do_fasin; break; case 0x0d: - fpufunctbl[mask] = fpuop_do_fatanh; + fpufunctbl[mask] = & FFPU fpuop_do_fatanh; break; case 0x0e: - fpufunctbl[mask] = fpuop_do_fsin; + fpufunctbl[mask] = & FFPU fpuop_do_fsin; break; case 0x0f: - fpufunctbl[mask] = fpuop_do_ftan; + fpufunctbl[mask] = & FFPU fpuop_do_ftan; break; case 0x10: - fpufunctbl[mask] = fpuop_do_fetox; + fpufunctbl[mask] = & FFPU fpuop_do_fetox; break; case 0x11: - fpufunctbl[mask] = fpuop_do_ftwotox; + fpufunctbl[mask] = & FFPU fpuop_do_ftwotox; break; case 0x12: - fpufunctbl[mask] = fpuop_do_ftentox; + fpufunctbl[mask] = & FFPU fpuop_do_ftentox; break; case 0x14: - fpufunctbl[mask] = fpuop_do_flogn; + fpufunctbl[mask] = & FFPU fpuop_do_flogn; break; case 0x15: - fpufunctbl[mask] = fpuop_do_flog10; + fpufunctbl[mask] = & FFPU fpuop_do_flog10; break; case 0x16: - fpufunctbl[mask] = fpuop_do_flog2; + fpufunctbl[mask] = & FFPU fpuop_do_flog2; break; case 0x18: - fpufunctbl[mask] = fpuop_do_fabs; + fpufunctbl[mask] = & FFPU fpuop_do_fabs; break; case 0x19: - fpufunctbl[mask] = fpuop_do_fcosh; + fpufunctbl[mask] = & FFPU fpuop_do_fcosh; break; case 0x1a: - fpufunctbl[mask] = fpuop_do_fneg; + fpufunctbl[mask] = & FFPU fpuop_do_fneg; break; case 0x1c: - fpufunctbl[mask] = fpuop_do_facos; + fpufunctbl[mask] = & FFPU fpuop_do_facos; break; case 0x1d: - fpufunctbl[mask] = fpuop_do_fcos; + fpufunctbl[mask] = & FFPU fpuop_do_fcos; break; case 0x1e: - fpufunctbl[mask] = fpuop_do_fgetexp; + fpufunctbl[mask] = & FFPU fpuop_do_fgetexp; break; case 0x1f: - fpufunctbl[mask] = fpuop_do_fgetman; + fpufunctbl[mask] = & FFPU fpuop_do_fgetman; break; case 0x20: - fpufunctbl[mask] = fpuop_do_fdiv; + fpufunctbl[mask] = & FFPU fpuop_do_fdiv; break; case 0x21: - fpufunctbl[mask] = fpuop_do_fmod; + fpufunctbl[mask] = & FFPU fpuop_do_fmod; break; case 0x22: - fpufunctbl[mask] = fpuop_do_fadd; + fpufunctbl[mask] = & FFPU fpuop_do_fadd; break; case 0x23: - fpufunctbl[mask] = fpuop_do_fmul; + fpufunctbl[mask] = & FFPU fpuop_do_fmul; break; case 0x24: - fpufunctbl[mask] = fpuop_do_fsgldiv; + fpufunctbl[mask] = & FFPU fpuop_do_fsgldiv; break; case 0x25: - fpufunctbl[mask] = fpuop_do_frem; + fpufunctbl[mask] = & FFPU fpuop_do_frem; break; case 0x26: - fpufunctbl[mask] = fpuop_do_fscale; + fpufunctbl[mask] = & FFPU fpuop_do_fscale; break; case 0x27: - fpufunctbl[mask] = fpuop_do_fsglmul; + fpufunctbl[mask] = & FFPU fpuop_do_fsglmul; break; case 0x28: - fpufunctbl[mask] = fpuop_do_fsub; + fpufunctbl[mask] = & FFPU fpuop_do_fsub; break; case 0x30: case 0x31: @@ -6026,13 +5858,13 @@ static void build_fpp_opp_lookup_table() case 0x35: case 0x36: case 0x37: - fpufunctbl[mask] = fpuop_do_fsincos; + fpufunctbl[mask] = & FFPU fpuop_do_fsincos; break; case 0x38: - fpufunctbl[mask] = fpuop_do_fcmp; + fpufunctbl[mask] = & FFPU fpuop_do_fcmp; break; case 0x3a: - fpufunctbl[mask] = fpuop_do_ftst; + fpufunctbl[mask] = & FFPU fpuop_do_ftst; break; } } @@ -6041,190 +5873,9 @@ static void build_fpp_opp_lookup_table() } } -static void build_fpsr_lookup_tables() -{ - uae_u32 i; - - // Mapping for "sw" -> fpsr condition code - for( i=0; i<0x48; i++ ) { - sw_cond_host2mac[i] = 0; - switch( (i << 8) & (SW_Z_I_NAN_MASK) ) { - case SW_UNSUPPORTED: - case SW_NAN: - case SW_EMPTY_REGISTER: - sw_cond_host2mac[i] |= 0x1000000; - break; - case SW_FINITE: - case SW_DENORMAL: - break; - case SW_I: - sw_cond_host2mac[i] |= 0x2000000; - break; - case SW_Z: - sw_cond_host2mac[i] |= 0x4000000; - break; - } - if( (i << 8) & SW_N ) { - sw_cond_host2mac[i] |= 0x8000000; - } - } - - // Mapping for fpsr condition code -> "sw" - for( i=0; i<16; i++ ) { - if( (i << 24) & 0x1000000 ) { - sw_cond_mac2host[i] = SW_NAN; - } else if( (i << 24) & 0x4000000 ) { - sw_cond_mac2host[i] = SW_Z; - } else if( (i << 24) & 0x2000000 ) { - sw_cond_mac2host[i] = SW_I; - } else { - sw_cond_mac2host[i] = SW_FINITE; - } - if( (i << 24) & 0x8000000 ) { - sw_cond_mac2host[i] |= SW_N; - } - } - - // Mapping for "sw" -> fpsr exception byte - for( i=0; i<0x80; i++ ) { - exception_host2mac[i] = 0; - - if(i & SW_FAKE_BSUN) { - exception_host2mac[i] |= BSUN; - } - // precision exception - if(i & SW_PE) { - exception_host2mac[i] |= INEX2; - } - // underflow exception - if(i & SW_UE) { - exception_host2mac[i] |= UNFL; - } - // overflow exception - if(i & SW_OE) { - exception_host2mac[i] |= OVFL; - } - // zero divide exception - if(i & SW_ZE) { - exception_host2mac[i] |= DZ; - } - // denormalized operand exception. - // wrong, but should not get here, normalization is done in elsewhere - if(i & SW_DE) { - exception_host2mac[i] |= SNAN; - } - // invalid operation exception - if(i & SW_IE) { - exception_host2mac[i] |= OPERR; - } - } - - // Mapping for fpsr exception byte -> "sw" - for( i=0; i<0x100; i++ ) { - int fpsr = (i << 8); - exception_mac2host[i] = 0; - - // BSUN; make sure that you don't generate FPU stack faults. - if(fpsr & BSUN) { - exception_mac2host[i] |= SW_FAKE_BSUN; - } - // precision exception - if(fpsr & INEX2) { - exception_mac2host[i] |= SW_PE; - } - // underflow exception - if(fpsr & UNFL) { - exception_mac2host[i] |= SW_UE; - } - // overflow exception - if(fpsr & OVFL) { - exception_mac2host[i] |= SW_OE; - } - // zero divide exception - if(fpsr & DZ) { - exception_mac2host[i] |= SW_ZE; - } - // denormalized operand exception - if(fpsr & SNAN) { - exception_mac2host[i] |= SW_DE; //Wrong - } - // invalid operation exception - if(fpsr & OPERR) { - exception_mac2host[i] |= SW_IE; - } - } - - /* - 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 "sw_accrued" -> fpsr accrued exception byte - for( i=0; i<0x40; i++ ) { - accrued_exception_host2mac[i] = 0; - - // precision exception - if(i & SW_PE) { - accrued_exception_host2mac[i] |= ACCR_INEX; - } - // underflow exception - if(i & SW_UE) { - accrued_exception_host2mac[i] |= ACCR_UNFL; - } - // overflow exception - if(i & SW_OE) { - accrued_exception_host2mac[i] |= ACCR_OVFL; - } - // zero divide exception - if(i & SW_ZE) { - accrued_exception_host2mac[i] |= ACCR_DZ; - } - // denormalized operand exception - if(i & SW_DE) { - accrued_exception_host2mac[i] |= ACCR_IOP; //?????? - } - // invalid operation exception - if(i & SW_IE) { - accrued_exception_host2mac[i] |= ACCR_IOP; - } - } - - // Mapping for fpsr accrued exception byte -> "sw_accrued" - for( i=0; i<0x20; i++ ) { - int fpsr = (i << 3); - accrued_exception_mac2host[i] = 0; - - // precision exception - if(fpsr & ACCR_INEX) { - accrued_exception_mac2host[i] |= SW_PE; - } - // underflow exception - if(fpsr & ACCR_UNFL) { - accrued_exception_mac2host[i] |= SW_UE; - } - // overflow exception - if(fpsr & ACCR_OVFL) { - accrued_exception_mac2host[i] |= SW_OE; - } - // zero divide exception - if(fpsr & ACCR_DZ) { - accrued_exception_mac2host[i] |= SW_ZE; - } - // What about SW_DE; //?????? - // invalid operation exception - if(fpsr & ACCR_IOP) { - accrued_exception_mac2host[i] |= SW_IE; - } - } -} - /* ---------------------------- CONSTANTS ---------------------------- */ -static void set_constant( float80 f, char *name, double value, uae_s32 mult ) +PRIVATE void FFPU set_constant ( fpu_register & f, char *name, double value, uae_s32 mult ) { FPU_CONSISTENCY_CHECK_START(); if(mult == 1) { @@ -6233,9 +5884,10 @@ static void set_constant( float80 f, char *name, double value, uae_s32 mult ) FLD QWORD PTR [value] FSTP TBYTE PTR [ESI] } */ - _ASM( "fldl %1\n" + __asm__ __volatile__( + "fldl %1\n" "fstpt %0\n" - : "=m" (*f) + : "=m" (f) : "m" (value) ); } else { @@ -6246,11 +5898,12 @@ static void set_constant( float80 f, char *name, double value, uae_s32 mult ) FMUL FSTP TBYTE PTR [ESI] } */ - _ASM( "fildl %2\n" + __asm__ __volatile__( + "fildl %2\n" "fldl %1\n" "fmul \n" "fstpt %0\n" - : "=m" (*f) + : "=m" (f) : "m" (value), "m" (mult) ); } @@ -6258,122 +5911,122 @@ static void set_constant( float80 f, char *name, double value, uae_s32 mult ) FPU_CONSISTENCY_CHECK_STOP( mult==1 ? "set_constant(mult==1)" : "set_constant(mult>1)" ); } -static void do_fldpi( float80 dest ) REGPARAM; -static void do_fldpi( float80 dest ) +PRIVATE void FFPU do_fldpi ( fpu_register & dest ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { FLDPI FXAM - FNSTSW sw + FNSTSW x86_status_word MOV EDI, [dest] FSTP TBYTE PTR [EDI] } */ - _ASM( "fldpi \n" + __asm__ __volatile__( + "fldpi \n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" - : "=m" (sw), "=m" (*dest) + : "=m" (x86_status_word), "=m" (dest) ); FPU_CONSISTENCY_CHECK_STOP("do_fldpi"); } -static void do_fldlg2( float80 dest ) REGPARAM; -static void do_fldlg2( float80 dest ) +PRIVATE void FFPU do_fldlg2 ( fpu_register & dest ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { FLDLG2 FXAM - FNSTSW sw + FNSTSW x86_status_word MOV EDI, [dest] FSTP TBYTE PTR [EDI] } */ - _ASM( "fldlg2 \n" + __asm__ __volatile__( + "fldlg2 \n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" - : "=m" (sw), "=m" (*dest) + : "=m" (x86_status_word), "=m" (dest) ); FPU_CONSISTENCY_CHECK_STOP("do_fldlg2"); } -static void do_fldl2e( float80 dest ) REGPARAM; -static void do_fldl2e( float80 dest ) +PRIVATE void FFPU do_fldl2e ( fpu_register & dest ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { FLDL2E FXAM - FNSTSW sw + FNSTSW x86_status_word MOV EDI, [dest] FSTP TBYTE PTR [EDI] } */ - _ASM( "fldl2e \n" + __asm__ __volatile__( + "fldl2e \n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" - : "=m" (sw), "=m" (*dest) + : "=m" (x86_status_word), "=m" (dest) ); FPU_CONSISTENCY_CHECK_STOP("do_fldl2e"); } -static void do_fldz( float80 dest ) REGPARAM; -static void do_fldz( float80 dest ) +PRIVATE void FFPU do_fldz ( fpu_register & dest ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { FLDZ FXAM - FNSTSW sw + FNSTSW x86_status_word MOV EDI, [dest] FSTP TBYTE PTR [EDI] } */ - _ASM( "fldz \n" + __asm__ __volatile__( + "fldz \n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" - : "=m" (sw), "=m" (*dest) + : "=m" (x86_status_word), "=m" (dest) ); FPU_CONSISTENCY_CHECK_STOP("do_fldz"); } -static void do_fldln2( float80 dest ) REGPARAM; -static void do_fldln2( float80 dest ) +PRIVATE void FFPU do_fldln2 ( fpu_register & dest ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { FLDLN2 FXAM - FNSTSW sw + FNSTSW x86_status_word MOV EDI, [dest] FSTP TBYTE PTR [EDI] } */ - _ASM( "fldln2 \n" + __asm__ __volatile__( + "fldln2 \n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" - : "=m" (sw), "=m" (*dest) + : "=m" (x86_status_word), "=m" (dest) ); FPU_CONSISTENCY_CHECK_STOP("do_fldln2"); } -static void do_fld1( float80 dest ) REGPARAM; -static void do_fld1( float80 dest ) +PRIVATE void FFPU do_fld1 ( fpu_register & dest ) { FPU_CONSISTENCY_CHECK_START(); /* _asm { FLD1 FXAM - FNSTSW sw + FNSTSW x86_status_word MOV EDI, [dest] FSTP TBYTE PTR [EDI] } */ - _ASM( "fld1 \n" + __asm__ __volatile__( + "fld1 \n" "fxam \n" "fnstsw %0\n" "fstpt %1\n" - : "=m" (sw), "=m" (*dest) + : "=m" (x86_status_word), "=m" (dest) ); FPU_CONSISTENCY_CHECK_STOP("do_fld1"); } @@ -6381,34 +6034,56 @@ static void do_fld1( float80 dest ) /* ---------------------------- MAIN INIT ---------------------------- */ -void fpu_init( void ) +#ifdef HAVE_SIGACTION +// Mega hackaround-that-happens-to-work: the following way to handle +// SIGFPE just happens to make the "fsave" below in fpu_init() *NOT* +// to abort with a floating point exception. However, we never +// actually reach sigfpe_handler(). +static void sigfpe_handler(int code, siginfo_t *sip, void *) { -/* _asm { - FSAVE m_fpu_state_original - } */ - _ASM("fsave %0" : "=m" (m_fpu_state_original)); + if (code == SIGFPE && sip->si_code == FPE_FLTINV) { + fprintf(stderr, "Invalid floating point operation\n"); + abort(); + } +} +#endif - regs.fpiar = 0; - regs.fpcr = 0; - regs.fpsr = 0; +PUBLIC void FFPU fpu_init( bool integral_68040 ) +{ + static bool done_first_time_initialization = false; + if (!done_first_time_initialization) { + fpu_init_native_fflags(); + fpu_init_native_exceptions(); + fpu_init_native_accrued_exceptions(); +#ifdef HAVE_SIGACTION + struct sigaction fpe_sa; + sigemptyset(&fpe_sa.sa_mask); + fpe_sa.sa_sigaction = sigfpe_handler; + fpe_sa.sa_flags = SA_SIGINFO; + sigaction(SIGFPE, &fpe_sa, 0); +#endif + done_first_time_initialization = true; + } - cw = CW_INITIAL; - sw = SW_INITIAL; - sw_accrued = 0; - sw_quotient = 0; + __asm__ __volatile__("fsave %0" : "=m" (m_fpu_state_original)); + + FPU is_integral = integral_68040; + FPU instruction_address = 0; + set_fpcr(0); + set_fpsr(0); + + x86_control_word = CW_INITIAL; + x86_status_word = SW_INITIAL; + x86_status_word_accrued = 0; + FPU fpsr.quotient = 0; for( int i=0; i<8; i++ ) { - MAKE_NAN( fp_reg[i] ); + MAKE_NAN( FPU registers[i] ); } - build_fpsr_lookup_tables(); build_fpp_opp_lookup_table(); -/* _asm { - FNINIT - FLDCW cw - } */ - _ASM("fninit\nfldcw %0" : : "m" (cw)); + __asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word)); do_fldpi( const_pi ); do_fldlg2( const_lg2 ); @@ -6435,28 +6110,16 @@ void fpu_init( void ) set_constant( const_1e4096, "1.0e4096", 1.0e256, 10000 ); // Just in case. -/* _asm { - FNINIT - FLDCW cw - } */ - _ASM("fninit\nfldcw %0" : : "m" (cw)); + __asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word)); } -void fpu_exit( void ) +PUBLIC void FFPU fpu_exit( void ) { -/* _asm { - FRSTOR m_fpu_state_original - // FNINIT - } */ - _ASM("frstor %0" : : "m" (m_fpu_state_original)); + __asm__ __volatile__("frstor %0" : : "m" (m_fpu_state_original)); } -void fpu_reset( void ) +PUBLIC void FFPU fpu_reset( void ) { fpu_exit(); - fpu_init(); + fpu_init(FPU is_integral); } - -#if DEBUG -#pragma optimize("",on) -#endif diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86.h b/BasiliskII/src/uae_cpu/fpu/fpu_x86.h index c1ddf030..4acdd8da 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_x86.h +++ b/BasiliskII/src/uae_cpu/fpu/fpu_x86.h @@ -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 */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h b/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h index e55ef066..ecdecfbc 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h +++ b/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.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 diff --git a/BasiliskII/src/uae_cpu/fpu/impl.h b/BasiliskII/src/uae_cpu/fpu/impl.h new file mode 100644 index 00000000..c4cbf903 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/impl.h @@ -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 */ diff --git a/BasiliskII/src/uae_cpu/fpu/mathlib.cpp b/BasiliskII/src/uae_cpu/fpu/mathlib.cpp new file mode 100644 index 00000000..adb8f5cf --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/mathlib.cpp @@ -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 diff --git a/BasiliskII/src/uae_cpu/fpu/mathlib.h b/BasiliskII/src/uae_cpu/fpu/mathlib.h new file mode 100644 index 00000000..514d6ae6 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/mathlib.h @@ -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 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 +#else +#include +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 ) --- */ +/* -------------------------------------------------------------------------- */ + +#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 */ diff --git a/BasiliskII/src/uae_cpu/fpu/rounding.cpp b/BasiliskII/src/uae_cpu/fpu/rounding.cpp new file mode 100644 index 00000000..5b86ca2d --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/rounding.cpp @@ -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 diff --git a/BasiliskII/src/uae_cpu/fpu/rounding.h b/BasiliskII/src/uae_cpu/fpu/rounding.h new file mode 100644 index 00000000..13268fc2 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/rounding.h @@ -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 */ diff --git a/BasiliskII/src/uae_cpu/fpu/types.h b/BasiliskII/src/uae_cpu/fpu/types.h new file mode 100644 index 00000000..3e11e14e --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/types.h @@ -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 */