1 |
/* |
2 |
* fpu/flags.h - Floating-point flags |
3 |
* |
4 |
* Basilisk II (C) 1997-2008 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_FLAGS_H |
29 |
#define FPU_FLAGS_H |
30 |
|
31 |
/* NOTE: this file shall be included only 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 flags */ |
45 |
#define FPU_USE_GENERIC_FLAGS |
46 |
|
47 |
/* -------------------------------------------------------------------------- */ |
48 |
/* --- Selection of floating-point flags handling mode --- */ |
49 |
/* -------------------------------------------------------------------------- */ |
50 |
|
51 |
/* Optimized i386 fpu core must use native flags */ |
52 |
#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY) |
53 |
# undef FPU_USE_GENERIC_FLAGS |
54 |
# define FPU_USE_X86_FLAGS |
55 |
#endif |
56 |
|
57 |
/* Old UAE FPU core can use native flags */ |
58 |
#if defined(FPU_UAE) && defined(USE_X87_ASSEMBLY) |
59 |
# undef FPU_USE_GENERIC_FLAGS |
60 |
# define FPU_USE_X86_FLAGS |
61 |
#endif |
62 |
|
63 |
/* IEEE-based implementation must use lazy flag evaluation */ |
64 |
#if defined(FPU_IEEE) |
65 |
# undef FPU_USE_GENERIC_FLAGS |
66 |
# define FPU_USE_LAZY_FLAGS |
67 |
#endif |
68 |
|
69 |
/* JIT Compilation for FPU only works with lazy evaluation of FPU flags */ |
70 |
#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) && defined(USE_JIT_FPU) |
71 |
# undef FPU_USE_GENERIC_FLAGS |
72 |
# define FPU_USE_LAZY_FLAGS |
73 |
#endif |
74 |
|
75 |
#ifdef FPU_IMPLEMENTATION |
76 |
|
77 |
/* -------------------------------------------------------------------------- */ |
78 |
/* --- Native X86 Floating-Point Flags --- */ |
79 |
/* -------------------------------------------------------------------------- */ |
80 |
|
81 |
/* FPU_X86 has its own set of lookup functions */ |
82 |
|
83 |
#ifdef FPU_USE_X86_FLAGS |
84 |
|
85 |
#define FPU_USE_NATIVE_FLAGS |
86 |
|
87 |
#define NATIVE_FFLAG_NEGATIVE 0x0200 |
88 |
#define NATIVE_FFLAG_ZERO 0x4000 |
89 |
#define NATIVE_FFLAG_INFINITY 0x0500 |
90 |
#define NATIVE_FFLAG_NAN 0x0100 |
91 |
|
92 |
/* Translation tables between native and m68k floating-point flags */ |
93 |
PRIVATE uae_u32 to_m68k_fpcond[0x48]; |
94 |
PRIVATE uae_u32 to_host_fpcond[0x10]; |
95 |
|
96 |
/* Truth table for floating-point condition codes */ |
97 |
PRIVATE uae_u32 fpcond_truth_table[32][8]; // 32 m68k conditions x 8 host condition codes |
98 |
|
99 |
/* Initialization */ |
100 |
PUBLIC void FFPU fpu_init_native_fflags(void); |
101 |
|
102 |
#ifdef FPU_UAE |
103 |
|
104 |
/* Native to m68k floating-point condition codes */ |
105 |
PRIVATE inline uae_u32 FFPU get_fpccr(void) |
106 |
{ return to_m68k_fpcond[(FPU fpsr.condition_codes >> 8) & 0x47]; } |
107 |
|
108 |
/* M68k to native floating-point condition codes */ |
109 |
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond) |
110 |
/* Precondition: new_fpcond is only valid for floating-point condition codes */ |
111 |
{ FPU fpsr.condition_codes = to_host_fpcond[new_fpcond >> 24]; } |
112 |
|
113 |
/* Make FPSR according to the value passed in argument */ |
114 |
PRIVATE inline void FFPU make_fpsr(fpu_register const & r) |
115 |
{ uae_u16 sw; __asm__ __volatile__ ("fxam\n\tfnstsw %0" : "=r" (sw) : "f" (r)); FPU fpsr.condition_codes = sw; } |
116 |
|
117 |
/* Return the corresponding ID of the current floating-point condition codes */ |
118 |
/* NOTE: only valid for evaluation of a condition */ |
119 |
PRIVATE inline int FFPU host_fpcond_id(void) |
120 |
{ return ((FPU fpsr.condition_codes >> 12) & 4) | ((FPU fpsr.condition_codes >> 8) & 3); } |
121 |
|
122 |
/* Return true if the floating-point condition is satisfied */ |
123 |
PRIVATE inline bool FFPU fpcctrue(int condition) |
124 |
{ return fpcond_truth_table[condition][host_fpcond_id()]; } |
125 |
|
126 |
#endif /* FPU_UAE */ |
127 |
|
128 |
/* Return the address of the floating-point condition codes truth table */ |
129 |
static inline uae_u8 * const FFPU address_of_fpcond_truth_table(void) |
130 |
{ return ((uae_u8*)&fpcond_truth_table[0][0]); } |
131 |
|
132 |
#endif /* FPU_X86_USE_NATIVE_FLAGS */ |
133 |
|
134 |
/* -------------------------------------------------------------------------- */ |
135 |
/* --- Use Original M68K FPU Mappings --- */ |
136 |
/* -------------------------------------------------------------------------- */ |
137 |
|
138 |
#ifdef FPU_USE_GENERIC_FLAGS |
139 |
|
140 |
#undef FPU_USE_NATIVE_FLAGS |
141 |
|
142 |
#define NATIVE_FFLAG_NEGATIVE 0x08000000 |
143 |
#define NATIVE_FFLAG_ZERO 0x04000000 |
144 |
#define NATIVE_FFLAG_INFINITY 0x02000000 |
145 |
#define NATIVE_FFLAG_NAN 0x01000000 |
146 |
|
147 |
/* Initialization - NONE */ |
148 |
PRIVATE inline void FFPU fpu_init_native_fflags(void) |
149 |
{ } |
150 |
|
151 |
/* Native to m68k floating-point condition codes - SELF */ |
152 |
PRIVATE inline uae_u32 FFPU get_fpccr(void) |
153 |
{ return FPU fpsr.condition_codes; } |
154 |
|
155 |
/* M68k to native floating-point condition codes - SELF */ |
156 |
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond) |
157 |
{ FPU fpsr.condition_codes = new_fpcond; } |
158 |
|
159 |
#endif /* FPU_USE_GENERIC_FLAGS */ |
160 |
|
161 |
/* -------------------------------------------------------------------------- */ |
162 |
/* --- Use Lazy Flags Evaluation --- */ |
163 |
/* -------------------------------------------------------------------------- */ |
164 |
|
165 |
#ifdef FPU_USE_LAZY_FLAGS |
166 |
|
167 |
#undef FPU_USE_NATIVE_FLAGS |
168 |
|
169 |
#define NATIVE_FFLAG_NEGATIVE 0x08000000 |
170 |
#define NATIVE_FFLAG_ZERO 0x04000000 |
171 |
#define NATIVE_FFLAG_INFINITY 0x02000000 |
172 |
#define NATIVE_FFLAG_NAN 0x01000000 |
173 |
|
174 |
/* Initialization - NONE */ |
175 |
PRIVATE inline void FFPU fpu_init_native_fflags(void) |
176 |
{ } |
177 |
|
178 |
/* Native to m68k floating-point condition codes - SELF */ |
179 |
PRIVATE inline uae_u32 FFPU get_fpccr(void) |
180 |
{ |
181 |
uae_u32 fpccr = 0; |
182 |
if (isnan(FPU result)) |
183 |
fpccr |= FPSR_CCB_NAN; |
184 |
else if (FPU result == 0.0) |
185 |
fpccr |= FPSR_CCB_ZERO; |
186 |
else if (FPU result < 0.0) |
187 |
fpccr |= FPSR_CCB_NEGATIVE; |
188 |
if (isinf(FPU result)) |
189 |
fpccr |= FPSR_CCB_INFINITY; |
190 |
return fpccr; |
191 |
} |
192 |
|
193 |
/* M68k to native floating-point condition codes - SELF */ |
194 |
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond) |
195 |
{ |
196 |
if (new_fpcond & FPSR_CCB_NAN) |
197 |
make_nan(FPU result); |
198 |
else if (new_fpcond & FPSR_CCB_ZERO) |
199 |
FPU result = 0.0; |
200 |
else if (new_fpcond & FPSR_CCB_NEGATIVE) |
201 |
FPU result = -1.0; |
202 |
else |
203 |
FPU result = +1.0; |
204 |
/* gb-- where is Infinity ? */ |
205 |
} |
206 |
|
207 |
/* Make FPSR according to the value passed in argument */ |
208 |
PRIVATE inline void FFPU make_fpsr(fpu_register const & r) |
209 |
{ FPU result = r; } |
210 |
|
211 |
#endif /* FPU_USE_LAZY_FLAGS */ |
212 |
|
213 |
#endif |
214 |
|
215 |
/* -------------------------------------------------------------------------- */ |
216 |
/* --- Common methods --- */ |
217 |
/* -------------------------------------------------------------------------- */ |
218 |
|
219 |
/* Return the address of the floating-point condition codes register */ |
220 |
static inline uae_u32 * const FFPU address_of_fpccr(void) |
221 |
{ return ((uae_u32 *)& FPU fpsr.condition_codes); } |
222 |
|
223 |
#endif /* FPU_FLAGS_H */ |