1 |
gbeauche |
1.1 |
/* |
2 |
|
|
* fpu/flags.cpp - Floating-point flags |
3 |
|
|
* |
4 |
gbeauche |
1.3 |
* Basilisk II (C) 1997-2005 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 |
|
|
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */ |
29 |
|
|
#undef PRIVATE |
30 |
|
|
#define PRIVATE /**/ |
31 |
|
|
|
32 |
|
|
#undef PUBLIC |
33 |
|
|
#define PUBLIC /**/ |
34 |
|
|
|
35 |
|
|
#undef FFPU |
36 |
|
|
#define FFPU /**/ |
37 |
|
|
|
38 |
|
|
#undef FPU |
39 |
|
|
#define FPU fpu. |
40 |
|
|
|
41 |
|
|
/* -------------------------------------------------------------------------- */ |
42 |
|
|
/* --- Native X86 floating-point flags --- */ |
43 |
|
|
/* -------------------------------------------------------------------------- */ |
44 |
|
|
|
45 |
|
|
#ifdef FPU_USE_X86_FLAGS |
46 |
|
|
|
47 |
|
|
/* Initialization */ |
48 |
|
|
void FFPU fpu_init_native_fflags(void) |
49 |
|
|
{ |
50 |
|
|
// Adapted from fpu_x86.cpp |
51 |
|
|
#define SW_Z_I_NAN_MASK (SW_C0|SW_C2|SW_C3) |
52 |
|
|
#define SW_Z (SW_C3) |
53 |
|
|
#define SW_I (SW_C0|SW_C2) |
54 |
|
|
#define SW_NAN (SW_C0) |
55 |
|
|
#define SW_FINITE (SW_C2) |
56 |
|
|
#define SW_EMPTY_REGISTER (SW_C0|SW_C3) |
57 |
|
|
#define SW_DENORMAL (SW_C2|SW_C3) |
58 |
|
|
#define SW_UNSUPPORTED (0) |
59 |
|
|
#define SW_N (SW_C1) |
60 |
|
|
|
61 |
|
|
// Sanity checks |
62 |
|
|
#if (SW_Z != NATIVE_FFLAG_ZERO) |
63 |
|
|
#error "Incorrect X86 Z fflag" |
64 |
|
|
#endif |
65 |
|
|
#if (SW_I != NATIVE_FFLAG_INFINITY) |
66 |
|
|
#error "Incorrect X86 I fflag" |
67 |
|
|
#endif |
68 |
|
|
#if (SW_N != NATIVE_FFLAG_NEGATIVE) |
69 |
|
|
#error "Incorrect X86 N fflag" |
70 |
|
|
#endif |
71 |
|
|
#if (SW_NAN != NATIVE_FFLAG_NAN) |
72 |
|
|
#error "Incorrect X86 NAN fflag" |
73 |
|
|
#endif |
74 |
|
|
|
75 |
|
|
// Native status word to m68k mappings |
76 |
|
|
for (uae_u32 i = 0; i < 0x48; i++) { |
77 |
|
|
to_m68k_fpcond[i] = 0; |
78 |
|
|
const uae_u32 native_fpcond = i << 8; |
79 |
|
|
switch (native_fpcond & SW_Z_I_NAN_MASK) { |
80 |
|
|
#ifndef FPU_UAE |
81 |
|
|
// gb-- enabling it would lead to incorrect drawing of digits |
82 |
|
|
// in Speedometer Performance Test |
83 |
|
|
case SW_UNSUPPORTED: |
84 |
|
|
#endif |
85 |
|
|
case SW_NAN: |
86 |
|
|
case SW_EMPTY_REGISTER: |
87 |
|
|
to_m68k_fpcond[i] |= FPSR_CCB_NAN; |
88 |
|
|
break; |
89 |
|
|
case SW_FINITE: |
90 |
|
|
case SW_DENORMAL: |
91 |
|
|
break; |
92 |
|
|
case SW_I: |
93 |
|
|
to_m68k_fpcond[i] |= FPSR_CCB_INFINITY; |
94 |
|
|
break; |
95 |
|
|
case SW_Z: |
96 |
|
|
to_m68k_fpcond[i] |= FPSR_CCB_ZERO; |
97 |
|
|
break; |
98 |
|
|
} |
99 |
|
|
if (native_fpcond & SW_N) |
100 |
|
|
to_m68k_fpcond[i] |= FPSR_CCB_NEGATIVE; |
101 |
|
|
} |
102 |
|
|
|
103 |
|
|
// m68k to native status word mappings |
104 |
|
|
for (uae_u32 i = 0; i < 0x10; i++) { |
105 |
|
|
const uae_u32 m68k_fpcond = i << 24; |
106 |
|
|
if (m68k_fpcond & FPSR_CCB_NAN) |
107 |
|
|
to_host_fpcond[i] = SW_NAN; |
108 |
|
|
else if (m68k_fpcond & FPSR_CCB_ZERO) |
109 |
|
|
to_host_fpcond[i] = SW_Z; |
110 |
|
|
else if (m68k_fpcond & FPSR_CCB_INFINITY) |
111 |
|
|
to_host_fpcond[i] = SW_I; |
112 |
|
|
else |
113 |
|
|
to_host_fpcond[i] = SW_FINITE; |
114 |
|
|
if (m68k_fpcond & FPSR_CCB_NEGATIVE) |
115 |
|
|
to_host_fpcond[i] |= SW_N; |
116 |
|
|
} |
117 |
|
|
|
118 |
|
|
// truth-table for FPU conditions |
119 |
|
|
for (uae_u32 host_fpcond = 0; host_fpcond < 0x08; host_fpcond++) { |
120 |
|
|
// host_fpcond: C3 on bit 2, C1 and C0 are respectively on bits 1 and 0 |
121 |
|
|
const uae_u32 real_host_fpcond = ((host_fpcond & 4) << 12) | ((host_fpcond & 3) << 8); |
122 |
|
|
const bool N = ((real_host_fpcond & NATIVE_FFLAG_NEGATIVE) == NATIVE_FFLAG_NEGATIVE); |
123 |
|
|
const bool Z = ((real_host_fpcond & NATIVE_FFLAG_ZERO) == NATIVE_FFLAG_ZERO); |
124 |
|
|
const bool NaN = ((real_host_fpcond & NATIVE_FFLAG_NAN) == NATIVE_FFLAG_NAN); |
125 |
|
|
|
126 |
|
|
int value; |
127 |
|
|
for (uae_u32 m68k_fpcond = 0; m68k_fpcond < 0x20; m68k_fpcond++) { |
128 |
|
|
switch (m68k_fpcond) { |
129 |
|
|
case 0x00: value = 0; break; // False |
130 |
|
|
case 0x01: value = Z; break; // Equal |
131 |
|
|
case 0x02: value = !(NaN || Z || N); break; // Ordered Greater Than |
132 |
|
|
case 0x03: value = Z || !(NaN || N); break; // Ordered Greater Than or Equal |
133 |
|
|
case 0x04: value = N && !(NaN || Z); break; // Ordered Less Than |
134 |
|
|
case 0x05: value = Z || (N && !NaN); break; // Ordered Less Than or Equal |
135 |
|
|
case 0x06: value = !(NaN || Z); break; // Ordered Greater or Less Than |
136 |
|
|
case 0x07: value = !NaN; break; // Ordered |
137 |
|
|
case 0x08: value = NaN; break; // Unordered |
138 |
|
|
case 0x09: value = NaN || Z; break; // Unordered or Equal |
139 |
|
|
case 0x0a: value = NaN || !(N || Z); break; // Unordered or Greater Than |
140 |
|
|
case 0x0b: value = NaN || Z || !N; break; // Unordered or Greater or Equal |
141 |
|
|
case 0x0c: value = NaN || (N && !Z); break; // Unordered or Less Than |
142 |
|
|
case 0x0d: value = NaN || Z || N; break; // Unordered or Less or Equal |
143 |
|
|
case 0x0e: value = !Z; break; // Not Equal |
144 |
|
|
case 0x0f: value = 1; break; // True |
145 |
|
|
case 0x10: value = 0; break; // Signaling False |
146 |
|
|
case 0x11: value = Z; break; // Signaling Equal |
147 |
|
|
case 0x12: value = !(NaN || Z || N); break; // Greater Than |
148 |
|
|
case 0x13: value = Z || !(NaN || N); break; // Greater Than or Equal |
149 |
|
|
case 0x14: value = N && !(NaN || Z); break; // Less Than |
150 |
|
|
case 0x15: value = Z || (N && !NaN); break; // Less Than or Equal |
151 |
|
|
case 0x16: value = !(NaN || Z); break; // Greater or Less Than |
152 |
|
|
case 0x17: value = !NaN; break; // Greater, Less or Equal |
153 |
|
|
case 0x18: value = NaN; break; // Not Greater, Less or Equal |
154 |
|
|
case 0x19: value = NaN || Z; break; // Not Greater or Less Than |
155 |
|
|
case 0x1a: value = NaN || !(N || Z); break; // Not Less Than or Equal |
156 |
|
|
case 0x1b: value = NaN || Z || !N; break; // Not Less Than |
157 |
|
|
case 0x1c: value = NaN || (N && !Z); break; // Not Greater Than or Equal |
158 |
|
|
// case 0x1c: value = !Z && (NaN || N); break; // Not Greater Than or Equal |
159 |
|
|
case 0x1d: value = NaN || Z || N; break; // Not Greater Than |
160 |
|
|
case 0x1e: value = !Z; break; // Signaling Not Equal |
161 |
|
|
case 0x1f: value = 1; break; // Signaling True |
162 |
|
|
default: value = -1; |
163 |
|
|
} |
164 |
|
|
fpcond_truth_table[m68k_fpcond][host_fpcond] = value; |
165 |
|
|
} |
166 |
|
|
} |
167 |
|
|
} |
168 |
|
|
|
169 |
|
|
#endif |