1 |
/* |
2 |
* fpu/rounding.h - system-dependant FPU rounding mode and precision |
3 |
* |
4 |
* Basilisk II (C) 1997-2005 Christian Bauer |
5 |
* |
6 |
* MC68881/68040 fpu emulation |
7 |
* |
8 |
* Original UAE FPU, copyright 1996 Herman ten Brugge |
9 |
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen |
10 |
* New framework, copyright 2000 Gwenole Beauchesne |
11 |
* Adapted for JIT compilation (c) Bernd Meyer, 2000 |
12 |
* |
13 |
* This program is free software; you can redistribute it and/or modify |
14 |
* it under the terms of the GNU General Public License as published by |
15 |
* the Free Software Foundation; either version 2 of the License, or |
16 |
* (at your option) any later version. |
17 |
* |
18 |
* This program is distributed in the hope that it will be useful, |
19 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
20 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
21 |
* GNU General Public License for more details. |
22 |
* |
23 |
* You should have received a copy of the GNU General Public License |
24 |
* along with this program; if not, write to the Free Software |
25 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
26 |
*/ |
27 |
|
28 |
#ifndef FPU_ROUNDING_H |
29 |
#define FPU_ROUNDING_H |
30 |
|
31 |
/* NOTE: this file shall be included from fpu/fpu_*.cpp */ |
32 |
#undef PUBLIC |
33 |
#define PUBLIC extern |
34 |
|
35 |
#undef PRIVATE |
36 |
#define PRIVATE static |
37 |
|
38 |
#undef FFPU |
39 |
#define FFPU /**/ |
40 |
|
41 |
#undef FPU |
42 |
#define FPU fpu. |
43 |
|
44 |
/* Defaults to generic rounding mode and precision handling */ |
45 |
#define FPU_USE_GENERIC_ROUNDING_MODE |
46 |
#define FPU_USE_GENERIC_ROUNDING_PRECISION |
47 |
|
48 |
/* -------------------------------------------------------------------------- */ |
49 |
/* --- Selection of floating-point rounding mode and precision --- */ |
50 |
/* -------------------------------------------------------------------------- */ |
51 |
|
52 |
/* Optimized i386 fpu core must use native rounding mode */ |
53 |
#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY) |
54 |
# undef FPU_USE_GENERIC_ROUNDING_MODE |
55 |
# define FPU_USE_X86_ROUNDING_MODE |
56 |
#endif |
57 |
|
58 |
/* Optimized i386 fpu core must use native rounding precision */ |
59 |
#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY) |
60 |
# undef FPU_USE_GENERIC_ROUNDING_PRECISION |
61 |
# define FPU_USE_X86_ROUNDING_PRECISION |
62 |
#endif |
63 |
|
64 |
#if 0 // gb-- FIXME: that doesn't work |
65 |
/* IEEE-based fpu core can have native rounding mode on i386 */ |
66 |
#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) |
67 |
# undef FPU_USE_GENERIC_ROUNDING_MODE |
68 |
# define FPU_USE_X86_ROUNDING_MODE |
69 |
#endif |
70 |
|
71 |
/* IEEE-based fpu core can have native rounding precision on i386 */ |
72 |
#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) |
73 |
# undef FPU_USE_GENERIC_ROUNDING_PRECISION |
74 |
# define FPU_USE_X86_ROUNDING_PRECISION |
75 |
#endif |
76 |
#endif |
77 |
|
78 |
/* -------------------------------------------------------------------------- */ |
79 |
/* --- Sanity checks --- */ |
80 |
/* -------------------------------------------------------------------------- */ |
81 |
|
82 |
/* X86 rounding mode and precision work together */ |
83 |
#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION) |
84 |
# define FPU_USE_X86_ROUNDING |
85 |
# 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) |
86 |
PRIVATE uae_u32 x86_control_word; |
87 |
#endif |
88 |
|
89 |
/* Control word -- rounding mode */ |
90 |
#ifdef FPU_USE_X86_ROUNDING_MODE |
91 |
PUBLIC const uae_u32 x86_control_word_rm_mac2host[]; |
92 |
#endif |
93 |
|
94 |
/* Control word -- rounding precision */ |
95 |
#ifdef FPU_USE_X86_ROUNDING_PRECISION |
96 |
PUBLIC const uae_u32 x86_control_word_rp_mac2host[]; |
97 |
#endif |
98 |
|
99 |
#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION) |
100 |
/* Set host control word for rounding mode and rounding precision */ |
101 |
PRIVATE inline void set_host_control_word(void) |
102 |
{ |
103 |
/* |
104 |
Exception enable byte is ignored, but the same value is returned |
105 |
that was previously set. |
106 |
*/ |
107 |
x86_control_word |
108 |
= (x86_control_word & ~(X86_ROUNDING_MODE|X86_ROUNDING_PRECISION)) |
109 |
| x86_control_word_rm_mac2host[(FPU fpcr.rounding_mode & FPCR_ROUNDING_MODE) >> 4] |
110 |
| x86_control_word_rp_mac2host[(FPU fpcr.rounding_precision & FPCR_ROUNDING_PRECISION) >> 6] |
111 |
; |
112 |
__asm__ __volatile__("fldcw %0" : : "m" (x86_control_word)); |
113 |
} |
114 |
#endif |
115 |
|
116 |
/* -------------------------------------------------------------------------- */ |
117 |
/* --- Generic rounding mode and precision --- */ |
118 |
/* -------------------------------------------------------------------------- */ |
119 |
|
120 |
#if defined(FPU_USE_GENERIC_ROUNDING_MODE) && defined(FPU_USE_GENERIC_ROUNDING_PRECISION) |
121 |
/* Set host control word for rounding mode and rounding precision */ |
122 |
PRIVATE inline void set_host_control_word(void) |
123 |
{ } |
124 |
#endif |
125 |
|
126 |
/* -------------------------------------------------------------------------- */ |
127 |
/* --- Common rounding mode and precision --- */ |
128 |
/* -------------------------------------------------------------------------- */ |
129 |
|
130 |
#if defined(FPU_USE_GENERIC_ROUNDING_MODE) || defined(FPU_USE_X86_ROUNDING_MODE) |
131 |
|
132 |
/* Return the current rounding mode in m68k format */ |
133 |
static inline uae_u32 FFPU get_rounding_mode(void) |
134 |
{ return FPU fpcr.rounding_mode; } |
135 |
|
136 |
/* Convert and set to native rounding mode */ |
137 |
static inline void FFPU set_rounding_mode(uae_u32 new_rounding_mode) |
138 |
{ FPU fpcr.rounding_mode = new_rounding_mode; } |
139 |
|
140 |
#endif |
141 |
|
142 |
#if defined(FPU_USE_GENERIC_ROUNDING_PRECISION) || defined(FPU_USE_X86_ROUNDING_PRECISION) |
143 |
|
144 |
/* Return the current rounding precision in m68k format */ |
145 |
static inline uae_u32 FFPU get_rounding_precision(void) |
146 |
{ return FPU fpcr.rounding_precision; } |
147 |
|
148 |
/* Convert and set to native rounding precision */ |
149 |
static inline void FFPU set_rounding_precision(uae_u32 new_rounding_precision) |
150 |
{ FPU fpcr.rounding_precision = new_rounding_precision; } |
151 |
|
152 |
#endif |
153 |
|
154 |
#endif /* FPU_ROUNDING_H */ |