1 |
gbeauche |
1.1 |
/* |
2 |
|
|
* fpu/flags.h - Floating-point flags |
3 |
|
|
* |
4 |
gbeauche |
1.6 |
* Basilisk II (C) 1997-2008 Christian Bauer |
5 |
gbeauche |
1.1 |
* |
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 |
gbeauche |
1.3 |
#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY) |
53 |
gbeauche |
1.1 |
# undef FPU_USE_GENERIC_FLAGS |
54 |
|
|
# define FPU_USE_X86_FLAGS |
55 |
|
|
#endif |
56 |
|
|
|
57 |
|
|
/* Old UAE FPU core can use native flags */ |
58 |
gbeauche |
1.3 |
#if defined(FPU_UAE) && defined(USE_X87_ASSEMBLY) |
59 |
gbeauche |
1.1 |
# 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 |
gbeauche |
1.3 |
#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) && defined(USE_JIT_FPU) |
71 |
gbeauche |
1.1 |
# 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 |
gbeauche |
1.2 |
static inline uae_u8 * const FFPU address_of_fpcond_truth_table(void) |
130 |
gbeauche |
1.1 |
{ 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 |
gbeauche |
1.2 |
static inline uae_u32 * const FFPU address_of_fpccr(void) |
221 |
gbeauche |
1.1 |
{ return ((uae_u32 *)& FPU fpsr.condition_codes); } |
222 |
|
|
|
223 |
|
|
#endif /* FPU_FLAGS_H */ |