1 |
/* |
2 |
* fpu/flags.cpp - 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 |
/* 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 |