2 * Fast486 386/486 CPU Emulation Library
5 * Copyright (C) 2015 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 /* INCLUDES *******************************************************************/
33 /* CONSTANTS ******************************************************************/
36 static const FAST486_FPU_DATA_REG FpuZero
= {0ULL, 0, FALSE
};
39 static const FAST486_FPU_DATA_REG FpuOne
= {0x8000000000000000ULL
, FPU_REAL10_BIAS
, FALSE
};
42 static const FAST486_FPU_DATA_REG FpuPi
= {0xC90FDAA22168C235ULL
, FPU_REAL10_BIAS
+ 1, FALSE
};
45 static const FAST486_FPU_DATA_REG FpuL2Ten
= {0xD49A784BCD1B8AFEULL
, FPU_REAL10_BIAS
+ 1, FALSE
};
48 static const FAST486_FPU_DATA_REG FpuL2E
= {0xB8AA3B295C17F0BCULL
, FPU_REAL10_BIAS
, FALSE
};
51 static const FAST486_FPU_DATA_REG FpuLgTwo
= {0x9A209A84FBCFF799ULL
, FPU_REAL10_BIAS
- 2, FALSE
};
54 static const FAST486_FPU_DATA_REG FpuLnTwo
= {0xB17217F7D1CF79ACULL
, FPU_REAL10_BIAS
- 1, FALSE
};
57 static const FAST486_FPU_DATA_REG FpuTwo
= {0x8000000000000000ULL
, FPU_REAL10_BIAS
+ 1, FALSE
};
60 static const FAST486_FPU_DATA_REG FpuHalfPi
= {0xC90FDAA22168C235ULL
, FPU_REAL10_BIAS
, FALSE
};
62 static const FAST486_FPU_DATA_REG FpuInverseNumber
[INVERSE_NUMBERS_COUNT
] =
64 {0x8000000000000000ULL
, FPU_REAL10_BIAS
, FALSE
}, /* 1 / 1 */
65 {0x8000000000000000ULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 1 / 2 */
66 {0xAAAAAAAAAAAAAAABULL
, FPU_REAL10_BIAS
- 2, FALSE
}, /* 1 / 3 */
67 {0x8000000000000000ULL
, FPU_REAL10_BIAS
- 2, FALSE
}, /* 1 / 4 */
68 {0xCCCCCCCCCCCCCCCDULL
, FPU_REAL10_BIAS
- 3, FALSE
}, /* 1 / 5 */
69 {0xAAAAAAAAAAAAAAAAULL
, FPU_REAL10_BIAS
- 3, FALSE
}, /* 1 / 6 */
70 {0x9249249249249249ULL
, FPU_REAL10_BIAS
- 3, FALSE
}, /* 1 / 7 */
71 {0x8000000000000000ULL
, FPU_REAL10_BIAS
- 3, FALSE
}, /* 1 / 8 */
72 {0xE38E38E38E38E38EULL
, FPU_REAL10_BIAS
- 4, FALSE
}, /* 1 / 9 */
73 {0xCCCCCCCCCCCCCCCDULL
, FPU_REAL10_BIAS
- 4, FALSE
}, /* 1 / 10 */
74 {0xBA2E8BA2E8BA2E8CULL
, FPU_REAL10_BIAS
- 4, FALSE
}, /* 1 / 11 */
75 {0xAAAAAAAAAAAAAAABULL
, FPU_REAL10_BIAS
- 4, FALSE
}, /* 1 / 12 */
76 {0x9D89D89D89D89D8AULL
, FPU_REAL10_BIAS
- 4, FALSE
}, /* 1 / 13 */
77 {0x9249249249249249ULL
, FPU_REAL10_BIAS
- 4, FALSE
}, /* 1 / 14 */
78 {0x8888888888888889ULL
, FPU_REAL10_BIAS
- 4, FALSE
}, /* 1 / 15 */
79 {0x8000000000000000ULL
, FPU_REAL10_BIAS
- 4, FALSE
}, /* 1 / 16 */
80 {0xF0F0F0F0F0F0F0F0ULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 17 */
81 {0xE38E38E38E38E38EULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 18 */
82 {0xD79435E50D79435EULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 19 */
83 {0xCCCCCCCCCCCCCCCDULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 20 */
84 {0xC30C30C30C30C30CULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 21 */
85 {0xBA2E8BA2E8BA2E8BULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 22 */
86 {0xB21642C8590B2164ULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 23 */
87 {0xAAAAAAAAAAAAAAABULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 24 */
88 {0xA3D70A3D70A3D70AULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 25 */
89 {0x9D89D89D89D89D8AULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 26 */
90 {0x97B425ED097B425FULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 27 */
91 {0x9249249249249249ULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 28 */
92 {0x8D3DCB08D3DCB08DULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 29 */
93 {0x8888888888888889ULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 30 */
94 {0x8421084210842108ULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 31 */
95 {0x8000000000000000ULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 32 */
96 {0xF83E0F83E0F83E0FULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 33 */
97 {0xF0F0F0F0F0F0F0F0ULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 34 */
98 {0xEA0EA0EA0EA0EA0EULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 35 */
99 {0xE38E38E38E38E38EULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 36 */
100 {0xDD67C8A60DD67C8AULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 37 */
101 {0xD79435E50D79435EULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 38 */
102 {0xD20D20D20D20D20DULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 39 */
103 {0xCCCCCCCCCCCCCCCDULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 40 */
104 {0xC7CE0C7CE0C7CE0CULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 41 */
105 {0xC30C30C30C30C30CULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 42 */
106 {0xBE82FA0BE82FA0BFULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 43 */
107 {0xBA2E8BA2E8BA2E8BULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 44 */
108 {0xB60B60B60B60B60BULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 45 */
109 {0xB21642C8590B2164ULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 46 */
110 {0xAE4C415C9882B931ULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 47 */
111 {0xAAAAAAAAAAAAAAABULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 48 */
112 {0xA72F05397829CBC1ULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 49 */
113 {0xA3D70A3D70A3D70AULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 50 */
116 static const FAST486_FPU_DATA_REG FpuInverseNumberSine
[INVERSE_NUMBERS_COUNT
] =
118 {0xAAAAAAAAAAAAAAAAULL
, FPU_REAL10_BIAS
- 3, FALSE
}, /* 1 / 6 */
119 {0xCCCCCCCCCCCCCCCCULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 20 */
120 {0xC30C30C30C30C30CULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 42 */
121 {0xE38E38E38E38E38EULL
, FPU_REAL10_BIAS
- 7, FALSE
}, /* 1 / 72 */
122 {0x94F2094F2094F209ULL
, FPU_REAL10_BIAS
- 7, FALSE
}, /* 1 / 110 */
123 {0xD20D20D20D20D20DULL
, FPU_REAL10_BIAS
- 8, FALSE
}, /* 1 / 156 */
124 {0x9C09C09C09C09C09ULL
, FPU_REAL10_BIAS
- 8, FALSE
}, /* 1 / 210 */
125 {0xF0F0F0F0F0F0F0F0ULL
, FPU_REAL10_BIAS
- 9, FALSE
}, /* 1 / 272 */
126 {0xBFA02FE80BFA02FEULL
, FPU_REAL10_BIAS
- 9, FALSE
}, /* 1 / 342 */
127 {0x9C09C09C09C09C09ULL
, FPU_REAL10_BIAS
- 9, FALSE
}, /* 1 / 420 */
128 {0x81848DA8FAF0D277ULL
, FPU_REAL10_BIAS
- 9, FALSE
}, /* 1 / 506 */
129 {0xDA740DA740DA740DULL
, FPU_REAL10_BIAS
- 10, FALSE
}, /* 1 / 600 */
130 {0xBAB656100BAB6561ULL
, FPU_REAL10_BIAS
- 10, FALSE
}, /* 1 / 702 */
131 {0xA16B312EA8FC377CULL
, FPU_REAL10_BIAS
- 10, FALSE
}, /* 1 / 812 */
132 {0x8CF008CF008CF008ULL
, FPU_REAL10_BIAS
- 10, FALSE
}, /* 1 / 930 */
133 {0xF83E0F83E0F83E0FULL
, FPU_REAL10_BIAS
- 11, FALSE
}, /* 1 / 1056 */
134 {0xDC4A00DC4A00DC4AULL
, FPU_REAL10_BIAS
- 11, FALSE
}, /* 1 / 1190 */
135 {0xC4CE07B00C4CE07BULL
, FPU_REAL10_BIAS
- 11, FALSE
}, /* 1 / 1332 */
136 {0xB0E2A2600B0E2A26ULL
, FPU_REAL10_BIAS
- 11, FALSE
}, /* 1 / 1482 */
137 {0x9FD809FD809FD809ULL
, FPU_REAL10_BIAS
- 11, FALSE
}, /* 1 / 1640 */
138 {0x9126D6E4802449B5ULL
, FPU_REAL10_BIAS
- 11, FALSE
}, /* 1 / 1806 */
139 {0x84655D9BAB2F1008ULL
, FPU_REAL10_BIAS
- 11, FALSE
}, /* 1 / 1980 */
140 {0xF2805AF0221A0CC9ULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 2162 */
141 {0xDEE95C4CA037BA57ULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 2352 */
142 {0xCD9A673400CD9A67ULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 2550 */
143 {0xBE3C310B84A4F832ULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 2756 */
144 {0xB087277A39941560ULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 2970 */
145 {0xA44029100A440291ULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 3192 */
146 {0x9936034AA9121AA1ULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 3422 */
147 {0x8F3F82A86DACA008ULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 3660 */
148 {0x8639F00218E7C008ULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 3906 */
149 {0xFC0FC0FC0FC0FC0FULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 4160 */
150 {0xED208916CF412FD1ULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 4422 */
151 {0xDF7B4EC93886702DULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 4692 */
152 {0xD2FB287C7224E167ULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 4970 */
153 {0xC78031E00C78031EULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 5256 */
154 {0xBCEEBFB33F021F2EULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 5550 */
155 {0xB32EB86E96D5D441ULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 5852 */
156 {0xAA2B0A62E08248F3ULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 6162 */
157 {0xA1D139855F7268EDULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 6480 */
158 {0x9A1100604AA03C2EULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 6806 */
159 {0x92DC0092DC0092DCULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 7140 */
160 {0x8C258008C258008CULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 7482 */
161 {0x85E230A32BAB46DDULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 7832 */
162 {0x8008008008008008ULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 8190 */
163 {0xF51BE2CC2D7AAC94ULL
, FPU_REAL10_BIAS
- 14, FALSE
}, /* 1 / 8556 */
164 {0xEAD7EC46DDA80C62ULL
, FPU_REAL10_BIAS
- 14, FALSE
}, /* 1 / 8930 */
165 {0xE135A9C97500E135ULL
, FPU_REAL10_BIAS
- 14, FALSE
}, /* 1 / 9312 */
166 {0xD8281B71177BDB7BULL
, FPU_REAL10_BIAS
- 14, FALSE
}, /* 1 / 9702 */
167 {0xCFA3892CE9FFCC17ULL
, FPU_REAL10_BIAS
- 14, FALSE
}, /* 1 / 10100 */
170 static const FAST486_FPU_DATA_REG FpuInverseNumberCosine
[INVERSE_NUMBERS_COUNT
] =
172 {0x8000000000000000ULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 1 / 2 */
173 {0xAAAAAAAAAAAAAAAAULL
, FPU_REAL10_BIAS
- 4, FALSE
}, /* 1 / 12 */
174 {0x8888888888888888ULL
, FPU_REAL10_BIAS
- 5, FALSE
}, /* 1 / 30 */
175 {0x9249249249249249ULL
, FPU_REAL10_BIAS
- 6, FALSE
}, /* 1 / 56 */
176 {0xB60B60B60B60B60BULL
, FPU_REAL10_BIAS
- 7, FALSE
}, /* 1 / 90 */
177 {0xF83E0F83E0F83E0FULL
, FPU_REAL10_BIAS
- 8, FALSE
}, /* 1 / 132 */
178 {0xB40B40B40B40B40BULL
, FPU_REAL10_BIAS
- 8, FALSE
}, /* 1 / 182 */
179 {0x8888888888888888ULL
, FPU_REAL10_BIAS
- 8, FALSE
}, /* 1 / 240 */
180 {0xD62B80D62B80D62BULL
, FPU_REAL10_BIAS
- 9, FALSE
}, /* 1 / 306 */
181 {0xAC7691840AC76918ULL
, FPU_REAL10_BIAS
- 9, FALSE
}, /* 1 / 380 */
182 {0x8DDA520237694808ULL
, FPU_REAL10_BIAS
- 9, FALSE
}, /* 1 / 462 */
183 {0xED7303B5CC0ED730ULL
, FPU_REAL10_BIAS
- 10, FALSE
}, /* 1 / 552 */
184 {0xC9A633FCD967300CULL
, FPU_REAL10_BIAS
- 10, FALSE
}, /* 1 / 650 */
185 {0xAD602B580AD602B5ULL
, FPU_REAL10_BIAS
- 10, FALSE
}, /* 1 / 756 */
186 {0x96A850096A850096ULL
, FPU_REAL10_BIAS
- 10, FALSE
}, /* 1 / 870 */
187 {0x8421084210842108ULL
, FPU_REAL10_BIAS
- 10, FALSE
}, /* 1 / 992 */
188 {0xE9A3D25E00E9A3D2ULL
, FPU_REAL10_BIAS
- 11, FALSE
}, /* 1 / 1122 */
189 {0xD00D00D00D00D00DULL
, FPU_REAL10_BIAS
- 11, FALSE
}, /* 1 / 1260 */
190 {0xBA7258200BA72582ULL
, FPU_REAL10_BIAS
- 11, FALSE
}, /* 1 / 1406 */
191 {0xA80A80A80A80A80AULL
, FPU_REAL10_BIAS
- 11, FALSE
}, /* 1 / 1560 */
192 {0x983B773A92E16009ULL
, FPU_REAL10_BIAS
- 11, FALSE
}, /* 1 / 1722 */
193 {0x8A8DCD1FEEAE465CULL
, FPU_REAL10_BIAS
- 11, FALSE
}, /* 1 / 1892 */
194 {0xFD477B6C956529CDULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 2070 */
195 {0xE865AC7B7603A196ULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 2256 */
196 {0xD5FEBF01E17D2DC4ULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 2450 */
197 {0xC5B200C5B200C5B2ULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 2652 */
198 {0xB7307B1492B1D28FULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 2862 */
199 {0xAA392F35DC17F00AULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 3080 */
200 {0x9E96394D47B46C68ULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 3306 */
201 {0x941A9CC82BF7E68BULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 3540 */
202 {0x8AA08EF5936D4008ULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 3782 */
203 {0x8208208208208208ULL
, FPU_REAL10_BIAS
- 12, FALSE
}, /* 1 / 4032 */
204 {0xF46C5E0BB22F800FULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 4290 */
205 {0xE6271BA5329217D3ULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 4556 */
206 {0xD918B2EF5B7B4866ULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 4830 */
207 {0xCD1ED923A7DCBEB2ULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 5112 */
208 {0xC21BDD800C21BDD8ULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 5402 */
209 {0xB7F5F08CD84C2BD5ULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 5700 */
210 {0xAE968C517F46800AULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 6006 */
211 {0xA5E9F6ED347F0721ULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 6320 */
212 {0x9DDEDA75A1CD4726ULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 6642 */
213 {0x9665EE14DB2283E4ULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 6972 */
214 {0x8F71AD362448008FULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 7310 */
215 {0x88F61A371B048C2BULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 7656 */
216 {0x82E88A942AB2D933ULL
, FPU_REAL10_BIAS
- 13, FALSE
}, /* 1 / 8010 */
217 {0xFA7EF5D91AC9538AULL
, FPU_REAL10_BIAS
- 14, FALSE
}, /* 1 / 8372 */
218 {0xEFE4D31416B96CFEULL
, FPU_REAL10_BIAS
- 14, FALSE
}, /* 1 / 8742 */
219 {0xE5F36CB00E5F36CBULL
, FPU_REAL10_BIAS
- 14, FALSE
}, /* 1 / 9120 */
220 {0xDC9D0ECFCB6E9378ULL
, FPU_REAL10_BIAS
- 14, FALSE
}, /* 1 / 9506 */
221 {0xD3D56292AB7E800DULL
, FPU_REAL10_BIAS
- 14, FALSE
}, /* 1 / 9900 */
224 static const FAST486_FPU_DATA_REG FpuInverseNumberAtan
[INVERSE_NUMBERS_COUNT
] =
226 {0xAAAAAAAAAAAAAAAAULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 2 / 3 */
227 {0xCCCCCCCCCCCCCCCCULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 4 / 5 */
228 {0xDB6DB6DB6DB6DB6DULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 6 / 7 */
229 {0xE38E38E38E38E38EULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 8 / 9 */
230 {0xE8BA2E8BA2E8BA2EULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 10 / 11 */
231 {0xEC4EC4EC4EC4EC4EULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 12 / 13 */
232 {0xEEEEEEEEEEEEEEEEULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 14 / 15 */
233 {0xF0F0F0F0F0F0F0F0ULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 16 / 17 */
234 {0xF286BCA1AF286BCAULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 18 / 19 */
235 {0xF3CF3CF3CF3CF3CFULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 20 / 21 */
236 {0xF4DE9BD37A6F4DE9ULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 22 / 23 */
237 {0xF5C28F5C28F5C28FULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 24 / 25 */
238 {0xF684BDA12F684BDAULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 26 / 27 */
239 {0xF72C234F72C234F7ULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 28 / 29 */
240 {0xF7BDEF7BDEF7BDEFULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 30 / 31 */
241 {0xF83E0F83E0F83E0FULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 32 / 33 */
242 {0xF8AF8AF8AF8AF8AFULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 34 / 35 */
243 {0xF914C1BACF914C1BULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 36 / 37 */
244 {0xF96F96F96F96F96FULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 38 / 39 */
245 {0xF9C18F9C18F9C18FULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 40 / 41 */
246 {0xFA0BE82FA0BE82FAULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 42 / 43 */
247 {0xFA4FA4FA4FA4FA4FULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 44 / 45 */
248 {0xFA8D9DF51B3BEA36ULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 46 / 47 */
249 {0xFAC687D6343EB1A1ULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 48 / 49 */
250 {0xFAFAFAFAFAFAFAFAULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 50 / 51 */
251 {0xFB2B78C13521CFB2ULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 52 / 53 */
252 {0xFB586FB586FB586FULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 54 / 55 */
253 {0xFB823EE08FB823EEULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 56 / 57 */
254 {0xFBA9386822B63CBEULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 58 / 59 */
255 {0xFBCDA3AC10C9714FULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 60 / 61 */
256 {0xFBEFBEFBEFBEFBEFULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 62 / 63 */
257 {0xFC0FC0FC0FC0FC0FULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 64 / 65 */
258 {0xFC2DD9CA81E9131AULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 66 / 67 */
259 {0xFC4A33F128CFC4A3ULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 68 / 69 */
260 {0xFC64F52EDF8C9EA5ULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 70 / 71 */
261 {0xFC7E3F1F8FC7E3F1ULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 72 / 73 */
262 {0xFC962FC962FC962FULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 74 / 75 */
263 {0xFCACE213F2B3884FULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 76 / 77 */
264 {0xFCC26E2D5DF984DCULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 78 / 79 */
265 {0xFCD6E9E06522C3F3ULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 80 / 81 */
266 {0xFCEA68DE12818ACBULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 82 / 83 */
267 {0xFCFCFCFCFCFCFCFCULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 84 / 85 */
268 {0xFD0EB66FD0EB66FDULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 86 / 87 */
269 {0xFD1FA3F47E8FD1FAULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 88 / 89 */
270 {0xFD2FD2FD2FD2FD2FULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 90 / 91 */
271 {0xFD3F4FD3F4FD3F4FULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 92 / 93 */
272 {0xFD4E25B9EFD4E25BULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 94 / 95 */
273 {0xFD5C5F02A3A0FD5CULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 96 / 97 */
274 {0xFD6A052BF5A814AFULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 98 / 99 */
275 {0xFD7720F353A4C0A2ULL
, FPU_REAL10_BIAS
- 1, FALSE
}, /* 100 / 101 */
278 /* PRIVATE FUNCTIONS **********************************************************/
280 #ifndef FAST486_NO_FPU
283 UnsignedMult128(ULONGLONG Multiplicand
,
284 ULONGLONG Multiplier
,
285 ULONGLONG
*HighProduct
)
287 ULONG MultiplicandLow
, MultiplicandHigh
, MultiplierLow
, MultiplierHigh
;
288 ULONG IntermediateLow
, IntermediateHigh
;
289 ULONGLONG LowProduct
, Intermediate
, Intermediate1
, Intermediate2
;
291 MultiplicandLow
= (ULONG
)(Multiplicand
& 0xFFFFFFFFULL
);
292 MultiplicandHigh
= (ULONG
)(Multiplicand
>> 32);
293 MultiplierLow
= (ULONG
)(Multiplier
& 0xFFFFFFFFULL
);
294 MultiplierHigh
= (ULONG
)(Multiplier
>> 32);
296 LowProduct
= (ULONGLONG
)MultiplicandLow
* (ULONGLONG
)MultiplierLow
;
297 Intermediate1
= (ULONGLONG
)MultiplicandLow
* (ULONGLONG
)MultiplierHigh
;
298 Intermediate2
= (ULONGLONG
)MultiplicandHigh
* (ULONGLONG
)MultiplierLow
;
299 *HighProduct
= (ULONGLONG
)MultiplicandHigh
* (ULONGLONG
)MultiplierHigh
;
301 Intermediate
= Intermediate1
+ Intermediate2
;
302 if (Intermediate
< Intermediate1
) *HighProduct
+= 1ULL << 32;
304 IntermediateLow
= (ULONG
)(Intermediate
& 0xFFFFFFFFULL
);
305 IntermediateHigh
= (ULONG
)(Intermediate
>> 32);
307 LowProduct
+= (ULONGLONG
)IntermediateLow
<< 32;
308 if ((ULONG
)(LowProduct
>> 32) < IntermediateLow
) (*HighProduct
)++;
310 *HighProduct
+= IntermediateHigh
;
315 UnsignedDivMod128(ULONGLONG DividendLow
,
316 ULONGLONG DividendHigh
,
318 PULONGLONG QuotientLow
,
319 PULONGLONG QuotientHigh
)
321 ULONGLONG ValueLow
= DividendLow
;
322 ULONGLONG ValueHigh
= DividendHigh
;
323 ULONGLONG CurrentLow
= 0ULL;
324 ULONGLONG CurrentHigh
= Divisor
;
327 ASSERT(Divisor
!= 0ULL);
329 /* Initialize the quotient */
330 *QuotientLow
= *QuotientHigh
= 0ULL;
332 /* Exit early if the dividend is lower than the divisor */
333 if ((DividendHigh
== 0ULL) && (DividendLow
< Divisor
)) return ValueLow
;
335 /* Normalize the current divisor */
336 Bits
= CountLeadingZeros64(CurrentHigh
);
337 CurrentHigh
<<= Bits
;
341 /* Shift the quotient left by one bit */
343 *QuotientHigh
|= *QuotientLow
>> 63;
346 /* Check if the value is higher than or equal to the current divisor */
347 if ((ValueHigh
> CurrentHigh
)
348 || ((ValueHigh
== CurrentHigh
) && (ValueLow
>= CurrentLow
)))
350 BOOLEAN Carry
= ValueLow
< CurrentLow
;
352 /* Subtract the current divisor from the value */
353 ValueHigh
-= CurrentHigh
;
354 ValueLow
-= CurrentLow
;
355 if (Carry
) ValueHigh
--;
357 /* Set the lowest bit of the quotient */
360 /* Stop if the value is lower than the original divisor */
361 if ((ValueHigh
== 0ULL) && (ValueLow
< Divisor
)) break;
364 /* Shift the current divisor right by one bit */
366 CurrentLow
|= (CurrentHigh
& 1) << 63;
371 * Calculate the number of significant bits the current
372 * divisor has more than the original divisor
374 Bits
= CountLeadingZeros64(Divisor
);
375 if (CurrentHigh
> 0ULL) Bits
+= 64 - CountLeadingZeros64(CurrentHigh
);
376 else Bits
-= CountLeadingZeros64(CurrentLow
);
380 *QuotientHigh
= *QuotientLow
;
387 /* Shift the quotient left by that amount */
388 *QuotientHigh
<<= Bits
;
389 *QuotientHigh
|= *QuotientLow
>> (64 - Bits
);
390 *QuotientLow
<<= Bits
;
393 /* Return the remainder */
397 static inline VOID FASTCALL
398 Fast486FpuRound(PFAST486_STATE State
,
402 INT RemainderHighBit
)
404 switch (State
->FpuControl
.Rc
)
406 case FPU_ROUND_NEAREST
:
408 /* Check if the highest bit of the remainder is set */
409 if (Remainder
& (1ULL << RemainderHighBit
))
413 /* Check if all the other bits are clear */
414 if (!(Remainder
& ((1ULL << RemainderHighBit
) - 1ULL)))
426 if ((Remainder
!= 0ULL) && Sign
) (*Result
)++;
432 if ((Remainder
!= 0ULL) && !Sign
) (*Result
)++;
438 /* Leave it truncated */
443 static inline VOID FASTCALL
444 Fast486FpuFromInteger(PFAST486_STATE State
,
446 PFAST486_FPU_DATA_REG Result
)
450 Result
->Sign
= Result
->Exponent
= Result
->Mantissa
= 0;
451 if (Value
== 0LL) return;
459 Result
->Mantissa
= (ULONGLONG
)Value
;
460 ZeroCount
= CountLeadingZeros64(Result
->Mantissa
);
462 Result
->Mantissa
<<= ZeroCount
;
463 Result
->Exponent
= FPU_REAL10_BIAS
+ 63 - ZeroCount
;
466 static inline BOOLEAN FASTCALL
467 Fast486FpuToInteger(PFAST486_STATE State
,
468 PCFAST486_FPU_DATA_REG Value
,
473 SHORT UnbiasedExp
= (SHORT
)Value
->Exponent
- FPU_REAL10_BIAS
;
475 if (FPU_IS_ZERO(Value
))
481 if (FPU_IS_NAN(Value
) || !FPU_IS_NORMALIZED(Value
) || (UnbiasedExp
>= 63))
483 /* Raise an invalid operation exception */
484 State
->FpuStatus
.Ie
= TRUE
;
486 if (State
->FpuControl
.Im
)
488 *Result
= 0x8000000000000000LL
;
497 if (UnbiasedExp
>= 0)
499 Bits
= 63 - UnbiasedExp
;
501 /* Calculate the result and the remainder */
502 *Result
= (LONGLONG
)(Value
->Mantissa
>> Bits
);
503 Remainder
= Value
->Mantissa
& ((1ULL << Bits
) - 1);
507 /* The result is zero */
511 if (UnbiasedExp
>= -64)
513 Remainder
= Value
->Mantissa
>> (-1 - UnbiasedExp
);
517 /* Too small to even have a remainder */
522 /* The result must be positive here */
523 ASSERT(*Result
>= 0LL);
525 /* Perform rounding */
526 Fast486FpuRound(State
, (PULONGLONG
)Result
, Value
->Sign
, Remainder
, Bits
- 1);
528 if (Value
->Sign
) *Result
= -*Result
;
532 static inline VOID FASTCALL
533 Fast486FpuFromSingleReal(PFAST486_STATE State
,
535 PFAST486_FPU_DATA_REG Result
)
537 /* Extract the sign, exponent and mantissa */
538 Result
->Sign
= (UCHAR
)(Value
>> 31);
539 Result
->Exponent
= (USHORT
)((Value
>> 23) & 0xFF);
540 Result
->Mantissa
= (((ULONGLONG
)Value
& 0x7FFFFFULL
) | 0x800000ULL
) << 40;
542 /* If this is a zero, we're done */
543 if (Value
== 0) return;
545 if (Result
->Exponent
== 0xFF) Result
->Exponent
= FPU_MAX_EXPONENT
+ 1;
548 /* Adjust the exponent bias */
549 Result
->Exponent
+= (FPU_REAL10_BIAS
- FPU_REAL4_BIAS
);
553 static inline BOOLEAN FASTCALL
554 Fast486FpuToSingleReal(PFAST486_STATE State
,
555 PCFAST486_FPU_DATA_REG Value
,
559 SHORT UnbiasedExp
= (SHORT
)Value
->Exponent
- FPU_REAL10_BIAS
;
562 if (FPU_IS_ZERO(Value
))
568 /* Calculate the mantissa */
569 *Result
= (ULONG
)(Value
->Mantissa
>> 40) & 0x7FFFFF;
571 if (FPU_IS_NAN(Value
))
573 *Result
|= FPU_REAL4_INFINITY
;
577 /* Check for underflow */
578 if (!FPU_IS_NORMALIZED(Value
) || (UnbiasedExp
< -127))
580 /* Raise the underflow exception */
581 State
->FpuStatus
.Ue
= TRUE
;
583 if (State
->FpuControl
.Um
)
585 /* The result is zero due to underflow */
595 /* Check for overflow */
596 if (UnbiasedExp
> 127)
598 /* Raise the overflow exception */
599 State
->FpuStatus
.Oe
= TRUE
;
601 if (State
->FpuControl
.Om
)
603 /* The result is infinity due to overflow */
604 *Result
= FPU_REAL4_INFINITY
;
613 /* Calculate the remainder */
614 Remainder
= Value
->Mantissa
& ((1ULL << 40) - 1);
616 /* Store the biased exponent */
617 *Result
|= (ULONG
)(UnbiasedExp
+ FPU_REAL4_BIAS
) << 23;
619 /* Perform rounding */
620 Result64
= (ULONGLONG
)*Result
;
621 Fast486FpuRound(State
, &Result64
, Value
->Sign
, Remainder
, 39);
622 *Result
= (ULONG
)Result64
;
626 if (Value
->Sign
) *Result
|= 0x80000000;
630 static inline VOID FASTCALL
631 Fast486FpuFromDoubleReal(PFAST486_STATE State
,
633 PFAST486_FPU_DATA_REG Result
)
635 /* Extract the sign, exponent and mantissa */
636 Result
->Sign
= (UCHAR
)(Value
>> 63);
637 Result
->Exponent
= (USHORT
)((Value
>> 52) & 0x7FF);
638 Result
->Mantissa
= (((ULONGLONG
)Value
& 0xFFFFFFFFFFFFFULL
) | 0x10000000000000ULL
) << 11;
640 /* If this is a zero, we're done */
641 if (Value
== 0) return;
643 if (Result
->Exponent
== 0x7FF) Result
->Exponent
= FPU_MAX_EXPONENT
+ 1;
646 /* Adjust the exponent bias */
647 Result
->Exponent
+= (FPU_REAL10_BIAS
- FPU_REAL8_BIAS
);
651 static inline BOOLEAN FASTCALL
652 Fast486FpuToDoubleReal(PFAST486_STATE State
,
653 PCFAST486_FPU_DATA_REG Value
,
657 SHORT UnbiasedExp
= (SHORT
)Value
->Exponent
- FPU_REAL10_BIAS
;
659 if (FPU_IS_ZERO(Value
))
665 /* Calculate the mantissa */
666 *Result
= (Value
->Mantissa
>> 11) & ((1ULL << 52) - 1);
668 if (FPU_IS_NAN(Value
))
670 *Result
|= FPU_REAL8_INFINITY
;
674 /* Check for underflow */
675 if (!FPU_IS_NORMALIZED(Value
) || (UnbiasedExp
< -1023))
677 /* Raise the underflow exception */
678 State
->FpuStatus
.Ue
= TRUE
;
680 if (State
->FpuControl
.Um
)
682 /* The result is zero due to underflow */
692 /* Check for overflow */
693 if (UnbiasedExp
> 1023)
695 /* Raise the overflow exception */
696 State
->FpuStatus
.Oe
= TRUE
;
698 if (State
->FpuControl
.Om
)
700 /* The result is infinity due to overflow */
701 *Result
= FPU_REAL8_INFINITY
;
710 /* Calculate the remainder */
711 Remainder
= Value
->Mantissa
& ((1ULL << 11) - 1ULL);
713 /* Store the biased exponent */
714 *Result
|= (ULONGLONG
)(UnbiasedExp
+ FPU_REAL8_BIAS
) << 52;
716 /* Perform rounding */
717 Fast486FpuRound(State
, Result
, Value
->Sign
, Remainder
, 10);
721 if (Value
->Sign
) *Result
|= 1ULL << 63;
725 static inline VOID FASTCALL
726 Fast486FpuFromPackedBcd(PFAST486_STATE State
,
728 PFAST486_FPU_DATA_REG Result
)
731 LONGLONG IntVal
= 0LL;
733 for (i
= 8; i
>= 0; i
--)
736 IntVal
+= (Value
[i
] >> 4) * 10 + (Value
[i
] & 0x0F);
740 if (Value
[9] & 0x80) IntVal
= -IntVal
;
742 /* Now convert the integer to FP80 */
743 Fast486FpuFromInteger(State
, IntVal
, Result
);
746 static inline BOOLEAN FASTCALL
747 Fast486FpuToPackedBcd(PFAST486_STATE State
,
748 PCFAST486_FPU_DATA_REG Value
,
754 /* Convert it to an integer first */
755 if (!Fast486FpuToInteger(State
, Value
, &IntVal
)) return FALSE
;
763 for (i
= 0; i
< 9; i
++)
765 Result
[i
] = (UCHAR
)((IntVal
% 10) + (((IntVal
/ 10) % 10) << 4));
772 static inline BOOLEAN FASTCALL
773 Fast486FpuAdd(PFAST486_STATE State
,
774 PCFAST486_FPU_DATA_REG FirstOperand
,
775 PCFAST486_FPU_DATA_REG SecondOperand
,
776 PFAST486_FPU_DATA_REG Result
)
778 FAST486_FPU_DATA_REG FirstAdjusted
= *FirstOperand
;
779 FAST486_FPU_DATA_REG SecondAdjusted
= *SecondOperand
;
780 FAST486_FPU_DATA_REG TempResult
;
782 if (FPU_IS_INDEFINITE(FirstOperand
)
783 || FPU_IS_INDEFINITE(SecondOperand
)
784 || (FPU_IS_POS_INF(FirstOperand
) && FPU_IS_NEG_INF(SecondOperand
))
785 || (FPU_IS_NEG_INF(FirstOperand
) && FPU_IS_POS_INF(SecondOperand
)))
787 /* The result will be indefinite */
789 Result
->Exponent
= FPU_MAX_EXPONENT
+ 1;
790 Result
->Mantissa
= FPU_INDEFINITE_MANTISSA
;
794 if ((!FPU_IS_NORMALIZED(FirstOperand
) || !FPU_IS_NORMALIZED(SecondOperand
)))
796 /* Raise the denormalized exception */
797 State
->FpuStatus
.De
= TRUE
;
799 if (!State
->FpuControl
.Dm
)
805 if (FPU_IS_ZERO(FirstOperand
) || FPU_IS_INFINITY(SecondOperand
))
807 /* The second operand is the result */
808 *Result
= *SecondOperand
;
812 if (FPU_IS_ZERO(SecondOperand
) || FPU_IS_INFINITY(FirstOperand
))
814 /* The first operand is the result */
815 *Result
= *FirstOperand
;
819 /* Find the largest exponent */
820 TempResult
.Exponent
= max(FirstOperand
->Exponent
, SecondOperand
->Exponent
);
822 /* Adjust the first operand to it... */
823 if (FirstAdjusted
.Exponent
< TempResult
.Exponent
)
825 if ((TempResult
.Exponent
- FirstAdjusted
.Exponent
) < 64)
827 FirstAdjusted
.Mantissa
>>= (TempResult
.Exponent
- FirstAdjusted
.Exponent
);
828 FirstAdjusted
.Exponent
= TempResult
.Exponent
;
832 /* The second operand is the result */
833 *Result
= *SecondOperand
;
838 /* ... and the second one too */
839 if (SecondAdjusted
.Exponent
< TempResult
.Exponent
)
841 if ((TempResult
.Exponent
- SecondAdjusted
.Exponent
) < 64)
843 SecondAdjusted
.Mantissa
>>= (TempResult
.Exponent
- SecondAdjusted
.Exponent
);
844 SecondAdjusted
.Exponent
= TempResult
.Exponent
;
848 /* The first operand is the result */
849 *Result
= *FirstOperand
;
854 if (FirstAdjusted
.Sign
== SecondAdjusted
.Sign
)
856 /* Calculate the mantissa and sign of the result */
857 TempResult
.Mantissa
= FirstAdjusted
.Mantissa
+ SecondAdjusted
.Mantissa
;
858 TempResult
.Sign
= FirstAdjusted
.Sign
;
862 /* Calculate the sign of the result */
863 if (FirstAdjusted
.Mantissa
> SecondAdjusted
.Mantissa
) TempResult
.Sign
= FirstAdjusted
.Sign
;
864 else if (FirstAdjusted
.Mantissa
< SecondAdjusted
.Mantissa
) TempResult
.Sign
= SecondAdjusted
.Sign
;
865 else TempResult
.Sign
= FALSE
;
867 /* Invert the negative mantissa */
868 if (FirstAdjusted
.Sign
) FirstAdjusted
.Mantissa
= -(LONGLONG
)FirstAdjusted
.Mantissa
;
869 if (SecondAdjusted
.Sign
) SecondAdjusted
.Mantissa
= -(LONGLONG
)SecondAdjusted
.Mantissa
;
871 /* Calculate the mantissa of the result */
872 TempResult
.Mantissa
= FirstAdjusted
.Mantissa
+ SecondAdjusted
.Mantissa
;
875 /* Did it overflow? */
876 if (FirstAdjusted
.Sign
== SecondAdjusted
.Sign
)
878 if (TempResult
.Mantissa
< FirstAdjusted
.Mantissa
879 || TempResult
.Mantissa
< SecondAdjusted
.Mantissa
)
881 if (TempResult
.Exponent
== FPU_MAX_EXPONENT
)
883 /* Raise the overflow exception */
884 State
->FpuStatus
.Oe
= TRUE
;
886 if (State
->FpuControl
.Om
)
888 /* Total overflow, return infinity */
889 TempResult
.Mantissa
= FPU_MANTISSA_HIGH_BIT
;
890 TempResult
.Exponent
= FPU_MAX_EXPONENT
+ 1;
899 /* Lose the LSB in favor of the carry */
900 TempResult
.Mantissa
>>= 1;
901 TempResult
.Mantissa
|= FPU_MANTISSA_HIGH_BIT
;
902 TempResult
.Exponent
++;
908 if (TempResult
.Mantissa
>= FirstAdjusted
.Mantissa
909 && TempResult
.Mantissa
>= SecondAdjusted
.Mantissa
)
911 /* Reverse the mantissa */
912 TempResult
.Mantissa
= -(LONGLONG
)TempResult
.Mantissa
;
916 /* Normalize the result and return it */
917 if (!Fast486FpuNormalize(State
, &TempResult
))
919 /* Exception occurred */
923 *Result
= TempResult
;
927 static inline BOOLEAN FASTCALL
928 Fast486FpuSubtract(PFAST486_STATE State
,
929 PCFAST486_FPU_DATA_REG FirstOperand
,
930 PCFAST486_FPU_DATA_REG SecondOperand
,
931 PFAST486_FPU_DATA_REG Result
)
933 FAST486_FPU_DATA_REG NegativeSecondOperand
= *SecondOperand
;
935 /* Invert the sign */
936 NegativeSecondOperand
.Sign
= !NegativeSecondOperand
.Sign
;
938 /* And perform an addition instead */
939 return Fast486FpuAdd(State
, FirstOperand
, &NegativeSecondOperand
, Result
);
942 static inline VOID FASTCALL
943 Fast486FpuCompare(PFAST486_STATE State
,
944 PCFAST486_FPU_DATA_REG FirstOperand
,
945 PCFAST486_FPU_DATA_REG SecondOperand
)
947 if (FPU_IS_NAN(FirstOperand
) || FPU_IS_NAN(SecondOperand
))
949 if ((FPU_IS_POS_INF(FirstOperand
)
950 && (!FPU_IS_NAN(SecondOperand
) || FPU_IS_NEG_INF(SecondOperand
)))
951 || (!FPU_IS_NAN(FirstOperand
) && FPU_IS_NEG_INF(SecondOperand
)))
953 State
->FpuStatus
.Code0
= FALSE
;
954 State
->FpuStatus
.Code2
= FALSE
;
955 State
->FpuStatus
.Code3
= FALSE
;
957 else if ((FPU_IS_POS_INF(SecondOperand
)
958 && (!FPU_IS_NAN(FirstOperand
) || FPU_IS_NEG_INF(FirstOperand
)))
959 || (!FPU_IS_NAN(SecondOperand
) && FPU_IS_NEG_INF(FirstOperand
)))
961 State
->FpuStatus
.Code0
= TRUE
;
962 State
->FpuStatus
.Code2
= FALSE
;
963 State
->FpuStatus
.Code3
= FALSE
;
967 State
->FpuStatus
.Code0
= TRUE
;
968 State
->FpuStatus
.Code2
= TRUE
;
969 State
->FpuStatus
.Code3
= TRUE
;
974 FAST486_FPU_DATA_REG TempResult
;
976 Fast486FpuSubtract(State
, FirstOperand
, SecondOperand
, &TempResult
);
978 if (FPU_IS_ZERO(&TempResult
))
980 State
->FpuStatus
.Code0
= FALSE
;
981 State
->FpuStatus
.Code2
= FALSE
;
982 State
->FpuStatus
.Code3
= TRUE
;
984 else if (TempResult
.Sign
)
986 State
->FpuStatus
.Code0
= TRUE
;
987 State
->FpuStatus
.Code2
= FALSE
;
988 State
->FpuStatus
.Code3
= FALSE
;
992 State
->FpuStatus
.Code0
= FALSE
;
993 State
->FpuStatus
.Code2
= FALSE
;
994 State
->FpuStatus
.Code3
= FALSE
;
999 static inline BOOLEAN FASTCALL
1000 Fast486FpuMultiply(PFAST486_STATE State
,
1001 PCFAST486_FPU_DATA_REG FirstOperand
,
1002 PCFAST486_FPU_DATA_REG SecondOperand
,
1003 PFAST486_FPU_DATA_REG Result
)
1005 FAST486_FPU_DATA_REG TempResult
;
1008 if (FPU_IS_INDEFINITE(FirstOperand
)
1009 || FPU_IS_INDEFINITE(SecondOperand
)
1010 || (FPU_IS_ZERO(FirstOperand
) && FPU_IS_INFINITY(SecondOperand
))
1011 || (FPU_IS_INFINITY(FirstOperand
) && FPU_IS_ZERO(SecondOperand
)))
1013 /* The result will be indefinite */
1014 Result
->Sign
= TRUE
;
1015 Result
->Exponent
= FPU_MAX_EXPONENT
+ 1;
1016 Result
->Mantissa
= FPU_INDEFINITE_MANTISSA
;
1020 if (FPU_IS_ZERO(FirstOperand
) || FPU_IS_ZERO(SecondOperand
))
1022 /* The result will be zero */
1023 Result
->Sign
= FirstOperand
->Sign
^ SecondOperand
->Sign
;
1024 Result
->Exponent
= 0;
1025 Result
->Mantissa
= 0ULL;
1029 if (FPU_IS_INFINITY(FirstOperand
) || FPU_IS_INFINITY(SecondOperand
))
1031 /* The result will be infinity */
1032 Result
->Sign
= FirstOperand
->Sign
^ SecondOperand
->Sign
;
1033 Result
->Exponent
= FPU_MAX_EXPONENT
+ 1;
1034 Result
->Mantissa
= FPU_MANTISSA_HIGH_BIT
;
1038 if ((!FPU_IS_NORMALIZED(FirstOperand
) || !FPU_IS_NORMALIZED(SecondOperand
)))
1040 /* Raise the denormalized exception */
1041 State
->FpuStatus
.De
= TRUE
;
1043 if (!State
->FpuControl
.Dm
)
1049 /* Calculate the sign */
1050 TempResult
.Sign
= FirstOperand
->Sign
^ SecondOperand
->Sign
;
1052 /* Calculate the exponent */
1053 Exponent
= (LONG
)FirstOperand
->Exponent
+ (LONG
)SecondOperand
->Exponent
- FPU_REAL10_BIAS
+ 1;
1055 /* Calculate the mantissa */
1056 UnsignedMult128(FirstOperand
->Mantissa
,
1057 SecondOperand
->Mantissa
,
1058 &TempResult
.Mantissa
);
1062 /* Raise the underflow exception */
1063 State
->FpuStatus
.Ue
= TRUE
;
1065 if (!State
->FpuControl
.Um
)
1070 /* The exponent will be zero */
1071 TempResult
.Exponent
= 0;
1073 /* If possible, denormalize the result, otherwise make it zero */
1074 if (Exponent
> -64) TempResult
.Mantissa
>>= (-Exponent
);
1075 else TempResult
.Mantissa
= 0ULL;
1077 else if (Exponent
> FPU_MAX_EXPONENT
)
1079 /* Raise the overflow exception */
1080 State
->FpuStatus
.Oe
= TRUE
;
1082 if (!State
->FpuControl
.Om
)
1087 /* Make the result infinity */
1088 TempResult
.Exponent
= FPU_MAX_EXPONENT
+ 1;
1089 TempResult
.Mantissa
= FPU_MANTISSA_HIGH_BIT
;
1091 else TempResult
.Exponent
= (USHORT
)Exponent
;
1093 /* Normalize the result */
1094 if (!Fast486FpuNormalize(State
, &TempResult
))
1096 /* Exception occurred */
1100 *Result
= TempResult
;
1104 static inline BOOLEAN FASTCALL
1105 Fast486FpuDivide(PFAST486_STATE State
,
1106 PCFAST486_FPU_DATA_REG FirstOperand
,
1107 PCFAST486_FPU_DATA_REG SecondOperand
,
1108 PFAST486_FPU_DATA_REG Result
)
1110 FAST486_FPU_DATA_REG TempResult
;
1111 ULONGLONG QuotientLow
, QuotientHigh
, Remainder
;
1114 if (FPU_IS_INDEFINITE(FirstOperand
)
1115 || FPU_IS_INDEFINITE(SecondOperand
)
1116 || (FPU_IS_INFINITY(FirstOperand
) && FPU_IS_INFINITY(SecondOperand
))
1117 || (FPU_IS_ZERO(FirstOperand
) && FPU_IS_ZERO(SecondOperand
)))
1119 /* Raise the invalid operation exception */
1120 State
->FpuStatus
.Ie
= TRUE
;
1122 if (State
->FpuControl
.Im
)
1124 /* Return the indefinite NaN */
1125 Result
->Sign
= TRUE
;
1126 Result
->Exponent
= FPU_MAX_EXPONENT
+ 1;
1127 Result
->Mantissa
= FPU_INDEFINITE_MANTISSA
;
1136 if (FPU_IS_ZERO(SecondOperand
) || FPU_IS_INFINITY(FirstOperand
))
1138 /* Raise the division by zero exception */
1139 State
->FpuStatus
.Ze
= TRUE
;
1141 if (State
->FpuControl
.Zm
)
1143 /* Return infinity */
1144 Result
->Sign
= FirstOperand
->Sign
;
1145 Result
->Exponent
= FPU_MAX_EXPONENT
+ 1;
1146 Result
->Mantissa
= FPU_MANTISSA_HIGH_BIT
;
1155 /* Calculate the sign of the result */
1156 TempResult
.Sign
= FirstOperand
->Sign
^ SecondOperand
->Sign
;
1158 if (FPU_IS_ZERO(FirstOperand
) || FPU_IS_INFINITY(SecondOperand
))
1161 Result
->Sign
= TempResult
.Sign
;
1162 Result
->Mantissa
= 0ULL;
1163 Result
->Exponent
= 0;
1167 /* Calculate the exponent of the result */
1168 Exponent
= (LONG
)FirstOperand
->Exponent
- (LONG
)SecondOperand
->Exponent
- 1;
1170 /* Divide the two mantissas */
1171 Remainder
= UnsignedDivMod128(0ULL,
1172 FirstOperand
->Mantissa
,
1173 SecondOperand
->Mantissa
,
1176 UNREFERENCED_PARAMETER(Remainder
); // TODO: Rounding
1178 TempResult
.Mantissa
= QuotientLow
;
1180 if (QuotientHigh
> 0ULL)
1182 ULONG BitsToShift
= 64 - CountLeadingZeros64(QuotientHigh
);
1184 TempResult
.Mantissa
>>= BitsToShift
;
1185 TempResult
.Mantissa
|= QuotientHigh
<< (64 - BitsToShift
);
1186 Exponent
+= BitsToShift
;
1191 if (Exponent
< -FPU_REAL10_BIAS
)
1193 TempResult
.Mantissa
>>= -(Exponent
+ FPU_REAL10_BIAS
);
1194 Exponent
= -FPU_REAL10_BIAS
;
1199 TempResult
.Exponent
= (USHORT
)(Exponent
+ FPU_REAL10_BIAS
);
1201 /* Normalize the result */
1202 if (!Fast486FpuNormalize(State
, &TempResult
))
1204 /* Exception occurred */
1208 *Result
= TempResult
;
1213 * Calculates using the identity:
1214 * 2 ^ x - 1 = 1 + sum { 2 * (((x - 1) * ln(2)) ^ n) / n! }
1216 static inline VOID FASTCALL
1217 Fast486FpuCalculateTwoPowerMinusOne(PFAST486_STATE State
,
1218 PCFAST486_FPU_DATA_REG Operand
,
1219 PFAST486_FPU_DATA_REG Result
)
1222 FAST486_FPU_DATA_REG TempResult
= FpuOne
;
1223 FAST486_FPU_DATA_REG Value
;
1224 FAST486_FPU_DATA_REG SeriesElement
;
1226 /* Calculate the first series element, which is 2 * (x - 1) * ln(2) */
1227 if (!Fast486FpuSubtract(State
, Operand
, &FpuOne
, &Value
)) return;
1228 if (!Fast486FpuMultiply(State
, &Value
, &FpuLnTwo
, &Value
)) return;
1229 if (!Fast486FpuAdd(State
, &Value
, &Value
, &SeriesElement
)) return;
1231 for (i
= 2; i
<= INVERSE_NUMBERS_COUNT
; i
++)
1233 /* Add the series element to the final sum */
1234 if (!Fast486FpuAdd(State
, &TempResult
, &SeriesElement
, &TempResult
))
1236 /* An exception occurred */
1241 * Calculate the next series element (partially) by multiplying
1242 * it with (x - 1) * ln(2)
1244 if (!Fast486FpuMultiply(State
, &SeriesElement
, &Value
, &SeriesElement
))
1246 /* An exception occurred */
1250 /* And now multiply the series element by the inverse counter */
1251 if (!Fast486FpuMultiply(State
,
1253 &FpuInverseNumber
[i
- 1],
1256 /* An exception occurred */
1261 *Result
= TempResult
;
1264 static inline BOOLEAN FASTCALL
1265 Fast486FpuCalculateLogBase2(PFAST486_STATE State
,
1266 PCFAST486_FPU_DATA_REG Operand
,
1267 PFAST486_FPU_DATA_REG Result
)
1270 FAST486_FPU_DATA_REG Value
= *Operand
;
1271 FAST486_FPU_DATA_REG TempResult
;
1272 FAST486_FPU_DATA_REG TempValue
;
1273 LONGLONG UnbiasedExp
= (LONGLONG
)Operand
->Exponent
- FPU_REAL10_BIAS
;
1277 /* Raise the invalid operation exception */
1278 State
->FpuStatus
.Ie
= TRUE
;
1280 if (State
->FpuControl
.Im
)
1282 /* Return the indefinite NaN */
1283 Result
->Sign
= TRUE
;
1284 Result
->Exponent
= FPU_MAX_EXPONENT
+ 1;
1285 Result
->Mantissa
= FPU_INDEFINITE_MANTISSA
;
1294 /* Get only the mantissa as a floating-pointer number between 1 and 2 */
1295 Value
.Exponent
= FPU_REAL10_BIAS
;
1297 /* Check if it's denormalized */
1298 if (!FPU_IS_NORMALIZED(&Value
))
1301 State
->FpuStatus
.De
= TRUE
;
1303 if (!State
->FpuControl
.Dm
)
1308 /* Normalize the number */
1309 Bits
= CountLeadingZeros64(Value
.Mantissa
);
1310 UnbiasedExp
-= Bits
;
1311 Value
.Mantissa
<<= Bits
;
1314 TempResult
.Sign
= FALSE
;
1315 TempResult
.Exponent
= FPU_REAL10_BIAS
- 1;
1316 TempResult
.Mantissa
= 0ULL;
1318 for (i
= 63; i
>= 0; i
--)
1320 /* Square the value */
1321 if (!Fast486FpuMultiply(State
, &Value
, &Value
, &Value
)) return FALSE
;
1323 /* Subtract two from it */
1324 if (!Fast486FpuSubtract(State
, &Value
, &FpuTwo
, &TempValue
)) return FALSE
;
1326 /* Is the result positive? */
1327 if (!TempValue
.Sign
)
1329 /* Yes, set the appropriate bit in the mantissa */
1330 TempResult
.Mantissa
|= 1ULL << i
;
1332 /* Halve the value */
1333 if (!Fast486FpuMultiply(State
, &Value
, &FpuInverseNumber
[1], &Value
)) return FALSE
;
1337 /* Normalize the result */
1338 if (!Fast486FpuNormalize(State
, &TempResult
)) return FALSE
;
1341 * Add the exponent to the result
1342 * log2(x * 2^y) = log2(x) + log2(2^y) = log2(x) + y
1344 Fast486FpuFromInteger(State
, UnbiasedExp
, &TempValue
);
1345 if (!Fast486FpuAdd(State
, &TempValue
, &TempResult
, &TempResult
)) return FALSE
;
1347 *Result
= TempResult
;
1351 static inline BOOLEAN FASTCALL
1352 Fast486FpuRemainder(PFAST486_STATE State
,
1353 PCFAST486_FPU_DATA_REG FirstOperand
,
1354 PCFAST486_FPU_DATA_REG SecondOperand
,
1355 BOOLEAN RoundToNearest
,
1356 PFAST486_FPU_DATA_REG Result OPTIONAL
,
1357 PLONGLONG Quotient OPTIONAL
)
1359 BOOLEAN Success
= FALSE
;
1360 INT OldRoundingMode
= State
->FpuControl
.Rc
;
1362 FAST486_FPU_DATA_REG Temp
;
1364 if (!Fast486FpuDivide(State
, FirstOperand
, SecondOperand
, &Temp
)) return FALSE
;
1366 State
->FpuControl
.Rc
= RoundToNearest
? FPU_ROUND_NEAREST
: FPU_ROUND_TRUNCATE
;
1368 if (!Fast486FpuToInteger(State
, &Temp
, &Integer
)) goto Cleanup
;
1372 Fast486FpuFromInteger(State
, Integer
, &Temp
);
1373 if (!Fast486FpuMultiply(State
, &Temp
, SecondOperand
, &Temp
)) goto Cleanup
;
1374 if (!Fast486FpuSubtract(State
, FirstOperand
, &Temp
, Result
)) goto Cleanup
;
1377 if (Quotient
) *Quotient
= Integer
;
1381 State
->FpuControl
.Rc
= OldRoundingMode
;
1386 * Calculates using the identity:
1387 * sin(x) = sum { -1^n * x^(2n + 1) / (2n + 1)!, n >= 0 }
1389 static inline BOOLEAN FASTCALL
1390 Fast486FpuCalculateSine(PFAST486_STATE State
,
1391 PCFAST486_FPU_DATA_REG Operand
,
1392 PFAST486_FPU_DATA_REG Result
)
1396 FAST486_FPU_DATA_REG Normalized
= *Operand
;
1397 FAST486_FPU_DATA_REG TempResult
;
1398 FAST486_FPU_DATA_REG OperandSquared
;
1399 FAST486_FPU_DATA_REG SeriesElement
;
1400 PCFAST486_FPU_DATA_REG Inverse
;
1402 if (!Fast486FpuRemainder(State
,
1407 (PLONGLONG
)&Quadrant
))
1412 /* Normalize the quadrant number */
1415 if (!(Quadrant
& 1))
1417 /* This is a sine */
1418 Inverse
= FpuInverseNumberSine
;
1419 TempResult
= SeriesElement
= Normalized
;
1423 /* This is a cosine */
1424 Inverse
= FpuInverseNumberCosine
;
1425 TempResult
= SeriesElement
= FpuOne
;
1428 /* Calculate the square of the operand */
1429 if (!Fast486FpuMultiply(State
, &Normalized
, &Normalized
, &OperandSquared
)) return FALSE
;
1431 for (i
= 0; i
< INVERSE_NUMBERS_COUNT
; i
++)
1433 if (!Fast486FpuMultiply(State
, &SeriesElement
, &OperandSquared
, &SeriesElement
))
1435 /* An exception occurred */
1439 if (!Fast486FpuMultiply(State
,
1444 /* An exception occurred */
1448 /* Toggle the sign of the series element */
1449 SeriesElement
.Sign
= !SeriesElement
.Sign
;
1451 if (!Fast486FpuAdd(State
, &TempResult
, &SeriesElement
, &TempResult
))
1453 /* An exception occurred */
1458 /* Flip the sign for the third and fourth quadrant */
1459 if (Quadrant
>= 2) TempResult
.Sign
= !TempResult
.Sign
;
1461 *Result
= TempResult
;
1466 * Calculates using the identity:
1467 * cos(x) = sum { -1^n * x^(2n) / (2n)!, n >= 0 }
1469 static inline BOOLEAN FASTCALL
1470 Fast486FpuCalculateCosine(PFAST486_STATE State
,
1471 PCFAST486_FPU_DATA_REG Operand
,
1472 PFAST486_FPU_DATA_REG Result
)
1474 FAST486_FPU_DATA_REG Value
= *Operand
;
1477 if (!Fast486FpuAdd(State
, &Value
, &FpuHalfPi
, &Value
)) return FALSE
;
1479 /* Calculate the sine */
1480 return Fast486FpuCalculateSine(State
, &Value
, Result
);
1483 static inline VOID FASTCALL
1484 Fast486FpuArithmeticOperation(PFAST486_STATE State
,
1486 PFAST486_FPU_DATA_REG Operand
,
1487 BOOLEAN TopDestination
)
1489 PFAST486_FPU_DATA_REG DestOperand
= TopDestination
? &FPU_ST(0) : Operand
;
1491 ASSERT(!(Operation
& ~7));
1493 /* Check the operation */
1499 Fast486FpuAdd(State
, &FPU_ST(0), Operand
, DestOperand
);
1506 Fast486FpuMultiply(State
, &FPU_ST(0), Operand
, DestOperand
);
1515 Fast486FpuCompare(State
, &FPU_ST(0), Operand
);
1516 if (Operation
== 3) Fast486FpuPop(State
);
1524 Fast486FpuSubtract(State
, &FPU_ST(0), Operand
, DestOperand
);
1531 Fast486FpuSubtract(State
, Operand
, &FPU_ST(0), DestOperand
);
1538 Fast486FpuDivide(State
, &FPU_ST(0), Operand
, DestOperand
);
1545 Fast486FpuDivide(State
, Operand
, &FPU_ST(0), DestOperand
);
1554 * x[n + 1] = (x[n] + s / x[n]) / 2
1556 static inline BOOLEAN FASTCALL
1557 Fast486FpuCalculateSquareRoot(PFAST486_STATE State
,
1558 PCFAST486_FPU_DATA_REG Operand
,
1559 PFAST486_FPU_DATA_REG Result
)
1561 FAST486_FPU_DATA_REG Value
= *Operand
;
1562 FAST486_FPU_DATA_REG PrevValue
= FpuZero
;
1566 /* Raise the invalid operation exception */
1567 State
->FpuStatus
.Ie
= TRUE
;
1569 if (State
->FpuControl
.Im
)
1571 /* Return the indefinite NaN */
1572 Result
->Sign
= TRUE
;
1573 Result
->Exponent
= FPU_MAX_EXPONENT
+ 1;
1574 Result
->Mantissa
= FPU_INDEFINITE_MANTISSA
;
1583 /* Loop until it converges */
1584 while (Value
.Sign
!= PrevValue
.Sign
1585 || Value
.Exponent
!= PrevValue
.Exponent
1586 || Value
.Mantissa
!= PrevValue
.Mantissa
)
1588 FAST486_FPU_DATA_REG Temp
;
1590 /* Save the current value */
1593 /* Divide the operand by the current value */
1594 if (!Fast486FpuDivide(State
, Operand
, &Value
, &Temp
)) return FALSE
;
1596 /* Add the result of that division to the current value */
1597 if (!Fast486FpuAdd(State
, &Value
, &Temp
, &Value
)) return FALSE
;
1599 /* Halve the current value */
1600 if (!Fast486FpuMultiply(State
, &Value
, &FpuInverseNumber
[1], &Value
)) return FALSE
;
1608 * Calculates arctan using Euler's formula:
1609 * arctan(x) = (x / (1 + x^2)) * sum { prod { (2j * x^2)
1610 * / ((2j + 1) * (1 + x^2)), j >= 1, j <= i }, i >= 0 }
1612 static inline BOOLEAN FASTCALL
1613 Fast486FpuCalculateArcTangent(PFAST486_STATE State
,
1614 PCFAST486_FPU_DATA_REG Numerator
,
1615 PCFAST486_FPU_DATA_REG Denominator
,
1616 PFAST486_FPU_DATA_REG Result
)
1619 BOOLEAN Inverted
= FALSE
;
1620 FAST486_FPU_DATA_REG TempNumerator
= *Numerator
;
1621 FAST486_FPU_DATA_REG TempDenominator
= *Denominator
;
1622 FAST486_FPU_DATA_REG Value
;
1623 FAST486_FPU_DATA_REG TempResult
;
1624 FAST486_FPU_DATA_REG ValDivValSqP1
;
1625 FAST486_FPU_DATA_REG SeriesElement
= FpuOne
;
1627 TempNumerator
.Sign
= FALSE
;
1628 TempDenominator
.Sign
= FALSE
;
1630 /* Compare the numerator to the denominator */
1631 if (!Fast486FpuSubtract(State
, &TempNumerator
, &TempDenominator
, &TempResult
))
1636 if ((Inverted
= !TempResult
.Sign
))
1638 if (!Fast486FpuDivide(State
, &TempDenominator
, &TempNumerator
, &Value
))
1645 if (!Fast486FpuDivide(State
, &TempNumerator
, &TempDenominator
, &Value
))
1651 /* Apparently, atan2(0, 0) = +/- 0 or +/- pi for some reason... */
1652 if (FPU_IS_INDEFINITE(&Value
)) Value
= FpuZero
;
1654 /* Calculate the value divided by the value squared plus one */
1655 if (!Fast486FpuMultiply(State
, &Value
, &Value
, &ValDivValSqP1
)) return FALSE
;
1656 if (!Fast486FpuAdd(State
, &ValDivValSqP1
, &FpuOne
, &ValDivValSqP1
)) return FALSE
;
1657 if (!Fast486FpuDivide(State
, &Value
, &ValDivValSqP1
, &ValDivValSqP1
)) return FALSE
;
1659 TempResult
= FpuOne
;
1661 for (i
= 0; i
< INVERSE_NUMBERS_COUNT
; i
++)
1663 if (!Fast486FpuMultiply(State
, &SeriesElement
, &Value
, &SeriesElement
))
1665 /* An exception occurred */
1669 if (!Fast486FpuMultiply(State
, &SeriesElement
, &ValDivValSqP1
, &SeriesElement
))
1671 /* An exception occurred */
1675 if (!Fast486FpuMultiply(State
,
1677 &FpuInverseNumberAtan
[i
],
1680 /* An exception occurred */
1684 if (!Fast486FpuAdd(State
, &TempResult
, &SeriesElement
, &TempResult
))
1686 /* An exception occurred */
1691 if (!Fast486FpuMultiply(State
, &TempResult
, &ValDivValSqP1
, &TempResult
))
1693 /* An exception occurred */
1699 /* Since y/x is positive, arctan(y/x) = pi/2 - arctan(x/y) */
1700 if (!Fast486FpuSubtract(State
, &FpuHalfPi
, &TempResult
, &TempResult
)) return FALSE
;
1703 /* Adjust the sign */
1704 if (!(!Numerator
->Sign
== !Denominator
->Sign
)) TempResult
.Sign
= !TempResult
.Sign
;
1706 if (Denominator
->Sign
)
1708 if (Numerator
->Sign
)
1711 if (!Fast486FpuSubtract(State
, &TempResult
, &FpuPi
, &TempResult
)) return FALSE
;
1716 if (!Fast486FpuAdd(State
, &TempResult
, &FpuPi
, &TempResult
)) return FALSE
;
1720 *Result
= TempResult
;
1724 static inline BOOLEAN FASTCALL
1725 Fast486FpuLoadEnvironment(PFAST486_STATE State
,
1732 if (!Fast486ReadMemory(State
, Segment
, Address
, FALSE
, Buffer
, (Size
+ 1) * 14))
1734 /* Exception occurred */
1738 /* Check if this is a 32-bit save or a 16-bit save */
1741 PULONG Data
= (PULONG
)Buffer
;
1743 State
->FpuControl
.Value
= (USHORT
)Data
[0];
1744 State
->FpuStatus
.Value
= (USHORT
)Data
[1];
1745 State
->FpuTag
= (USHORT
)Data
[2];
1746 State
->FpuLastInstPtr
.Long
= Data
[3];
1747 State
->FpuLastCodeSel
= (USHORT
)Data
[4];
1748 State
->FpuLastOpPtr
.Long
= Data
[5];
1749 State
->FpuLastDataSel
= (USHORT
)Data
[6];
1753 PUSHORT Data
= (PUSHORT
)Buffer
;
1755 State
->FpuControl
.Value
= Data
[0];
1756 State
->FpuStatus
.Value
= Data
[1];
1757 State
->FpuTag
= Data
[2];
1758 State
->FpuLastInstPtr
.LowWord
= Data
[3];
1759 State
->FpuLastCodeSel
= Data
[4];
1760 State
->FpuLastOpPtr
.LowWord
= Data
[5];
1761 State
->FpuLastDataSel
= Data
[6];
1767 static inline BOOLEAN FASTCALL
1768 Fast486FpuSaveEnvironment(PFAST486_STATE State
,
1775 /* Check if this is a 32-bit save or a 16-bit save */
1778 PULONG Data
= (PULONG
)Buffer
;
1780 Data
[0] = (ULONG
)State
->FpuControl
.Value
;
1781 Data
[1] = (ULONG
)State
->FpuStatus
.Value
;
1782 Data
[2] = (ULONG
)State
->FpuTag
;
1783 Data
[3] = State
->FpuLastInstPtr
.Long
;
1784 Data
[4] = (ULONG
)State
->FpuLastCodeSel
;
1785 Data
[5] = State
->FpuLastOpPtr
.Long
;
1786 Data
[6] = (ULONG
)State
->FpuLastDataSel
;
1790 PUSHORT Data
= (PUSHORT
)Buffer
;
1792 Data
[0] = State
->FpuControl
.Value
;
1793 Data
[1] = State
->FpuStatus
.Value
;
1794 Data
[2] = State
->FpuTag
;
1795 Data
[3] = State
->FpuLastInstPtr
.LowWord
;
1796 Data
[4] = State
->FpuLastCodeSel
;
1797 Data
[5] = State
->FpuLastOpPtr
.LowWord
;
1798 Data
[6] = State
->FpuLastDataSel
;
1801 return Fast486WriteMemory(State
, Segment
, Address
, Buffer
, (Size
+ 1) * 14);
1806 /* PUBLIC FUNCTIONS ***********************************************************/
1808 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8
)
1810 FAST486_MOD_REG_RM ModRegRm
;
1811 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1812 #ifndef FAST486_NO_FPU
1813 PFAST486_FPU_DATA_REG Operand
;
1814 FAST486_FPU_DATA_REG MemoryData
;
1817 TOGGLE_ADSIZE(AddressSize
);
1819 /* Get the operands */
1820 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1822 /* Exception occurred */
1828 #ifndef FAST486_NO_FPU
1830 Fast486FpuExceptionCheck(State
);
1831 FPU_SAVE_LAST_INST();
1833 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
1835 /* Raise the invalid operation exception */
1836 State
->FpuStatus
.Ie
= TRUE
;
1838 if (State
->FpuControl
.Im
)
1840 /* Return the indefinite NaN */
1841 FPU_ST(0).Sign
= TRUE
;
1842 FPU_ST(0).Exponent
= FPU_MAX_EXPONENT
+ 1;
1843 FPU_ST(0).Mantissa
= FPU_INDEFINITE_MANTISSA
;
1845 FPU_SET_TAG(0, FPU_TAG_SPECIAL
);
1851 if (ModRegRm
.Memory
)
1853 /* Load the source operand from memory */
1856 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
1858 /* Exception occurred */
1862 Fast486FpuFromSingleReal(State
, Value
, &MemoryData
);
1863 Operand
= &MemoryData
;
1865 FPU_SAVE_LAST_OPERAND();
1869 if (FPU_GET_TAG(ModRegRm
.SecondRegister
) == FPU_TAG_EMPTY
)
1871 /* Raise the invalid operation exception */
1872 State
->FpuStatus
.Ie
= TRUE
;
1874 if (State
->FpuControl
.Im
)
1876 /* Return the indefinite NaN */
1877 FPU_ST(0).Sign
= TRUE
;
1878 FPU_ST(0).Exponent
= FPU_MAX_EXPONENT
+ 1;
1879 FPU_ST(0).Mantissa
= FPU_INDEFINITE_MANTISSA
;
1881 FPU_SET_TAG(0, FPU_TAG_SPECIAL
);
1887 /* Load the source operand from an FPU register */
1888 Operand
= &FPU_ST(ModRegRm
.SecondRegister
);
1891 /* Perform the requested operation */
1892 Fast486FpuArithmeticOperation(State
, ModRegRm
.Register
, Operand
, TRUE
);
1897 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9
)
1899 FAST486_MOD_REG_RM ModRegRm
;
1900 BOOLEAN OperandSize
, AddressSize
;
1902 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1903 TOGGLE_OPSIZE(OperandSize
);
1904 TOGGLE_ADSIZE(AddressSize
);
1906 /* Get the operands */
1907 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1909 /* Exception occurred */
1915 #ifndef FAST486_NO_FPU
1917 if (ModRegRm
.Memory
)
1919 switch (ModRegRm
.Register
)
1925 FAST486_FPU_DATA_REG MemoryData
;
1927 Fast486FpuExceptionCheck(State
);
1928 FPU_SAVE_LAST_INST();
1929 FPU_SAVE_LAST_OPERAND();
1931 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
1933 /* Exception occurred */
1937 Fast486FpuFromSingleReal(State
, Value
, &MemoryData
);
1938 Fast486FpuPush(State
, &MemoryData
);
1948 ULONG Value
= FPU_REAL4_INDEFINITE
;
1950 Fast486FpuExceptionCheck(State
);
1951 FPU_SAVE_LAST_INST();
1952 FPU_SAVE_LAST_OPERAND();
1954 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
1956 /* Raise the invalid operation exception */
1957 State
->FpuStatus
.Ie
= TRUE
;
1959 if (!State
->FpuControl
.Im
)
1964 else if (!Fast486FpuToSingleReal(State
, &FPU_ST(0), &Value
))
1966 /* Exception occurred */
1970 if (!Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
))
1972 /* Exception occurred */
1976 if (ModRegRm
.Register
== 3) Fast486FpuPop(State
);
1983 Fast486FpuLoadEnvironment(State
,
1984 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1985 ? State
->SegmentOverride
: FAST486_REG_DS
,
1986 ModRegRm
.MemoryAddress
,
1994 Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &State
->FpuControl
.Value
);
2001 Fast486FpuSaveEnvironment(State
,
2002 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
2003 ? State
->SegmentOverride
: FAST486_REG_DS
,
2004 ModRegRm
.MemoryAddress
,
2012 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, State
->FpuControl
.Value
);
2019 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2026 switch ((ModRegRm
.Register
<< 3) | ModRegRm
.SecondRegister
)
2038 Fast486FpuExceptionCheck(State
);
2039 FPU_SAVE_LAST_INST();
2041 if (FPU_GET_TAG(ModRegRm
.SecondRegister
) == FPU_TAG_EMPTY
)
2043 /* Raise the invalid operation exception */
2044 State
->FpuStatus
.Ie
= TRUE
;
2046 if (!State
->FpuControl
.Im
)
2052 Fast486FpuPush(State
, &FPU_ST(ModRegRm
.SecondRegister
));
2066 FAST486_FPU_DATA_REG Temp
;
2068 Fast486FpuExceptionCheck(State
);
2069 FPU_SAVE_LAST_INST();
2071 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
2072 || FPU_GET_TAG(ModRegRm
.SecondRegister
) == FPU_TAG_EMPTY
)
2074 State
->FpuStatus
.Ie
= TRUE
;
2080 FPU_ST(0) = FPU_ST(ModRegRm
.SecondRegister
);
2081 FPU_ST(ModRegRm
.SecondRegister
) = Temp
;
2084 FPU_UPDATE_TAG(ModRegRm
.SecondRegister
);
2106 Fast486FpuExceptionCheck(State
);
2107 FPU_SAVE_LAST_INST();
2109 FPU_ST(ModRegRm
.SecondRegister
) = FPU_ST(0);
2110 FPU_UPDATE_TAG(ModRegRm
.SecondRegister
);
2112 Fast486FpuPop(State
);
2119 Fast486FpuExceptionCheck(State
);
2120 FPU_SAVE_LAST_INST();
2122 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
2124 State
->FpuStatus
.Ie
= TRUE
;
2128 /* Invert the sign */
2129 FPU_ST(0).Sign
= !FPU_ST(0).Sign
;
2137 Fast486FpuExceptionCheck(State
);
2138 FPU_SAVE_LAST_INST();
2140 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
2142 State
->FpuStatus
.Ie
= TRUE
;
2146 /* Set the sign to positive */
2147 FPU_ST(0).Sign
= FALSE
;
2155 Fast486FpuExceptionCheck(State
);
2156 FPU_SAVE_LAST_INST();
2158 Fast486FpuCompare(State
, &FPU_ST(0), &FpuZero
);
2165 Fast486FpuExceptionCheck(State
);
2166 FPU_SAVE_LAST_INST();
2168 /* The sign bit goes in C1, even if the register's empty */
2169 State
->FpuStatus
.Code1
= FPU_ST(0).Sign
;
2171 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
2173 State
->FpuStatus
.Code0
= 1;
2174 State
->FpuStatus
.Code2
= 0;
2175 State
->FpuStatus
.Code3
= 1;
2177 else if (FPU_GET_TAG(0) == FPU_TAG_SPECIAL
)
2179 if (FPU_IS_INFINITY(&FPU_ST(0)))
2181 State
->FpuStatus
.Code0
= 1;
2182 State
->FpuStatus
.Code2
= 1;
2183 State
->FpuStatus
.Code3
= 0;
2187 State
->FpuStatus
.Code0
= 1;
2188 State
->FpuStatus
.Code2
= 0;
2189 State
->FpuStatus
.Code3
= 0;
2192 else if (FPU_GET_TAG(0) == FPU_TAG_ZERO
)
2194 State
->FpuStatus
.Code0
= 0;
2195 State
->FpuStatus
.Code2
= 0;
2196 State
->FpuStatus
.Code3
= 1;
2200 if (FPU_IS_NORMALIZED(&FPU_ST(0)))
2202 State
->FpuStatus
.Code0
= 0;
2203 State
->FpuStatus
.Code2
= 1;
2204 State
->FpuStatus
.Code3
= 0;
2208 State
->FpuStatus
.Code0
= 0;
2209 State
->FpuStatus
.Code2
= 1;
2210 State
->FpuStatus
.Code3
= 1;
2232 PCFAST486_FPU_DATA_REG Constants
[] =
2243 Fast486FpuExceptionCheck(State
);
2244 FPU_SAVE_LAST_INST();
2246 Fast486FpuPush(State
, Constants
[ModRegRm
.SecondRegister
]);
2253 Fast486FpuExceptionCheck(State
);
2254 FPU_SAVE_LAST_INST();
2256 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
2258 State
->FpuStatus
.Ie
= TRUE
;
2262 if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2264 State
->FpuStatus
.De
= TRUE
;
2266 if (!State
->FpuControl
.Dm
)
2272 Fast486FpuCalculateTwoPowerMinusOne(State
, &FPU_ST(0), &FPU_ST(0));
2281 FAST486_FPU_DATA_REG Logarithm
;
2283 Fast486FpuExceptionCheck(State
);
2284 FPU_SAVE_LAST_INST();
2286 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
|| FPU_GET_TAG(1) == FPU_TAG_EMPTY
)
2288 State
->FpuStatus
.Ie
= TRUE
;
2292 if (!Fast486FpuCalculateLogBase2(State
, &FPU_ST(0), &Logarithm
))
2294 /* Exception occurred */
2298 if (!Fast486FpuMultiply(State
, &Logarithm
, &FPU_ST(1), &FPU_ST(1)))
2300 /* Exception occurred */
2304 /* Pop the stack so that the result ends up in ST0 */
2305 Fast486FpuPop(State
);
2314 FAST486_FPU_DATA_REG Sine
;
2315 FAST486_FPU_DATA_REG Cosine
;
2318 Fast486FpuExceptionCheck(State
);
2319 FPU_SAVE_LAST_INST();
2321 /* Compute the sine */
2322 if (!Fast486FpuCalculateSine(State
, &FPU_ST(0), &Sine
)) break;
2324 /* Normalize the angle */
2325 if (!Fast486FpuRemainder(State
,
2330 (PLONGLONG
)&Quadrant
))
2335 /* Normalize the quadrant number */
2338 /* Find the cosine by calculating sqrt(1 - sin(x) ^ 2) */
2339 if (!Fast486FpuMultiply(State
, &Sine
, &Sine
, &Cosine
)) break;
2340 if (!Fast486FpuSubtract(State
, &FpuOne
, &Cosine
, &Cosine
)) break;
2341 if (!Fast486FpuCalculateSquareRoot(State
, &Cosine
, &Cosine
)) break;
2343 /* Adjust the sign of the cosine */
2344 if (Quadrant
== 1 || Quadrant
== 2) Cosine
.Sign
= TRUE
;
2346 /* Divide the sine by the cosine to get the tangent */
2347 if (!Fast486FpuDivide(State
, &Sine
, &Cosine
, &FPU_ST(0))) break;
2351 Fast486FpuPush(State
, &FpuOne
);
2358 Fast486FpuExceptionCheck(State
);
2359 FPU_SAVE_LAST_INST();
2361 if (!Fast486FpuCalculateArcTangent(State
,
2371 Fast486FpuPop(State
);
2378 FAST486_FPU_DATA_REG Value
= FPU_ST(0);
2380 Fast486FpuExceptionCheck(State
);
2381 FPU_SAVE_LAST_INST();
2383 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
) || FPU_IS_INDEFINITE(&Value
))
2385 State
->FpuStatus
.Ie
= TRUE
;
2386 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
) State
->FpuStatus
.Sf
= TRUE
;
2390 if (FPU_IS_ZERO(&Value
))
2392 /* The exponent of zero is negative infinity */
2393 FPU_ST(0).Sign
= TRUE
;
2394 FPU_ST(0).Exponent
= FPU_MAX_EXPONENT
+ 1;
2395 FPU_ST(0).Mantissa
= FPU_MANTISSA_HIGH_BIT
;
2397 else if (FPU_IS_INFINITY(&Value
))
2399 /* The exponent of infinity is positive infinity */
2400 FPU_ST(0).Sign
= FALSE
;
2401 FPU_ST(0).Exponent
= FPU_MAX_EXPONENT
+ 1;
2402 FPU_ST(0).Mantissa
= FPU_MANTISSA_HIGH_BIT
;
2406 /* Store the unbiased exponent in ST0 */
2407 Fast486FpuFromInteger(State
,
2408 (LONGLONG
)Value
.Exponent
- (LONGLONG
)FPU_REAL10_BIAS
,
2412 /* Now push the mantissa as a real number, with the original sign */
2413 Value
.Exponent
= FPU_REAL10_BIAS
;
2414 Fast486FpuPush(State
, &Value
);
2426 Fast486FpuExceptionCheck(State
);
2427 FPU_SAVE_LAST_INST();
2429 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
|| FPU_GET_TAG(1) == FPU_TAG_EMPTY
)
2431 State
->FpuStatus
.Ie
= TRUE
;
2435 if (Fast486FpuRemainder(State
,
2438 ModRegRm
.Register
== 6, /* TRUE if it's FPREM1 */
2444 /* Return the lowest 3 bits of the quotient in C1, C3, C0 */
2445 State
->FpuStatus
.Code1
= Quotient
& 1;
2446 State
->FpuStatus
.Code3
= (Quotient
>> 1) & 1;
2447 State
->FpuStatus
.Code0
= (Quotient
>> 2) & 1;
2456 State
->FpuStatus
.Top
--;
2463 State
->FpuStatus
.Top
++;
2470 FAST486_FPU_DATA_REG Value
, Logarithm
;
2472 Fast486FpuExceptionCheck(State
);
2473 FPU_SAVE_LAST_INST();
2475 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
|| FPU_GET_TAG(1) == FPU_TAG_EMPTY
)
2477 State
->FpuStatus
.Ie
= TRUE
;
2481 if (!Fast486FpuAdd(State
, &FPU_ST(0), &FpuOne
, &Value
))
2483 /* Exception occurred */
2487 if (!Fast486FpuCalculateLogBase2(State
, &Value
, &Logarithm
))
2489 /* Exception occurred */
2493 if (!Fast486FpuMultiply(State
, &Logarithm
, &FPU_ST(1), &FPU_ST(1)))
2495 /* Exception occurred */
2499 /* Pop the stack so that the result ends up in ST0 */
2500 Fast486FpuPop(State
);
2509 Fast486FpuExceptionCheck(State
);
2510 FPU_SAVE_LAST_INST();
2512 Fast486FpuCalculateSquareRoot(State
, &FPU_ST(0), &FPU_ST(0));
2521 FAST486_FPU_DATA_REG Number
= FPU_ST(0);
2523 Fast486FpuExceptionCheck(State
);
2524 FPU_SAVE_LAST_INST();
2526 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
2528 State
->FpuStatus
.Ie
= TRUE
;
2532 if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2534 State
->FpuStatus
.De
= TRUE
;
2536 if (!State
->FpuControl
.Dm
)
2542 /* Replace FP0 with the sine */
2543 if (!Fast486FpuCalculateSine(State
, &Number
, &FPU_ST(0))) break;
2546 /* Push the cosine */
2547 if (!Fast486FpuCalculateCosine(State
, &Number
, &Number
)) break;
2548 Fast486FpuPush(State
, &Number
);
2556 LONGLONG Result
= 0LL;
2558 Fast486FpuExceptionCheck(State
);
2559 FPU_SAVE_LAST_INST();
2561 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
2563 State
->FpuStatus
.Ie
= TRUE
;
2567 if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2569 State
->FpuStatus
.De
= TRUE
;
2571 if (!State
->FpuControl
.Dm
)
2577 /* Do nothing if it's too big to not be an integer */
2578 if (FPU_ST(0).Exponent
>= FPU_REAL10_BIAS
+ 63) break;
2580 /* Perform the rounding */
2581 Fast486FpuToInteger(State
, &FPU_ST(0), &Result
);
2582 Fast486FpuFromInteger(State
, Result
, &FPU_ST(0));
2584 State
->FpuStatus
.Pe
= TRUE
;
2592 LONGLONG UnbiasedExp
= (LONGLONG
)((SHORT
)FPU_ST(0).Exponent
) - FPU_REAL10_BIAS
;
2593 INT OldRoundingMode
= State
->FpuControl
.Rc
;
2595 Fast486FpuExceptionCheck(State
);
2596 FPU_SAVE_LAST_INST();
2598 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
|| FPU_GET_TAG(1) == FPU_TAG_EMPTY
)
2600 State
->FpuStatus
.Ie
= TRUE
;
2604 if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2606 State
->FpuStatus
.De
= TRUE
;
2608 if (!State
->FpuControl
.Dm
)
2614 State
->FpuControl
.Rc
= FPU_ROUND_TRUNCATE
;
2616 if (!Fast486FpuToInteger(State
, &FPU_ST(1), &Scale
))
2618 /* Exception occurred */
2619 State
->FpuControl
.Rc
= OldRoundingMode
;
2623 State
->FpuControl
.Rc
= OldRoundingMode
;
2625 /* Adjust the unbiased exponent */
2626 UnbiasedExp
+= Scale
;
2628 /* Check for underflow */
2629 if (UnbiasedExp
< -1023)
2631 /* Raise the underflow exception */
2632 State
->FpuStatus
.Ue
= TRUE
;
2634 if (State
->FpuControl
.Um
)
2636 /* Make the result zero */
2637 FPU_ST(0) = FpuZero
;
2644 /* Check for overflow */
2645 if (UnbiasedExp
> 1023)
2647 /* Raise the overflow exception */
2648 State
->FpuStatus
.Oe
= TRUE
;
2650 if (State
->FpuControl
.Om
)
2652 /* Make the result infinity */
2653 FPU_ST(0).Mantissa
= FPU_MANTISSA_HIGH_BIT
;
2654 FPU_ST(0).Exponent
= FPU_MAX_EXPONENT
+ 1;
2661 FPU_ST(0).Exponent
= (USHORT
)(UnbiasedExp
+ FPU_REAL10_BIAS
);
2670 Fast486FpuExceptionCheck(State
);
2671 FPU_SAVE_LAST_INST();
2673 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
2675 State
->FpuStatus
.Ie
= TRUE
;
2679 if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2681 State
->FpuStatus
.De
= TRUE
;
2683 if (!State
->FpuControl
.Dm
)
2689 Fast486FpuCalculateSine(State
, &FPU_ST(0), &FPU_ST(0));
2698 Fast486FpuExceptionCheck(State
);
2699 FPU_SAVE_LAST_INST();
2701 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
2703 State
->FpuStatus
.Ie
= TRUE
;
2707 if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2709 State
->FpuStatus
.De
= TRUE
;
2711 if (!State
->FpuControl
.Dm
)
2717 Fast486FpuCalculateCosine(State
, &FPU_ST(0), &FPU_ST(0));
2726 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2735 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA
)
2737 FAST486_MOD_REG_RM ModRegRm
;
2738 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2739 #ifndef FAST486_NO_FPU
2741 FAST486_FPU_DATA_REG MemoryData
;
2744 TOGGLE_ADSIZE(AddressSize
);
2746 /* Get the operands */
2747 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2749 /* Exception occurred */
2755 #ifndef FAST486_NO_FPU
2757 Fast486FpuExceptionCheck(State
);
2758 FPU_SAVE_LAST_INST();
2760 if (!ModRegRm
.Memory
)
2762 /* The only valid opcode in this case is FUCOMPP (0xDA 0xE9) */
2763 if ((ModRegRm
.Register
!= 5) && (ModRegRm
.SecondRegister
!= 1))
2765 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2769 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
) || (FPU_GET_TAG(1) == FPU_TAG_EMPTY
))
2771 /* Raise the invalid operation exception*/
2772 State
->FpuStatus
.Ie
= TRUE
;
2777 Fast486FpuCompare(State
, &FPU_ST(0), &FPU_ST(1));
2780 Fast486FpuPop(State
);
2781 Fast486FpuPop(State
);
2786 FPU_SAVE_LAST_OPERAND();
2788 /* Load the source operand from memory */
2789 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, (PULONG
)&Value
))
2791 /* Exception occurred */
2795 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
2797 /* Raise the invalid operation exception */
2798 State
->FpuStatus
.Ie
= TRUE
;
2800 if (State
->FpuControl
.Im
)
2802 /* Return the indefinite NaN */
2803 FPU_ST(0).Sign
= TRUE
;
2804 FPU_ST(0).Exponent
= FPU_MAX_EXPONENT
+ 1;
2805 FPU_ST(0).Mantissa
= FPU_INDEFINITE_MANTISSA
;
2807 FPU_SET_TAG(0, FPU_TAG_SPECIAL
);
2813 Fast486FpuFromInteger(State
, (LONGLONG
)Value
, &MemoryData
);
2815 /* Perform the requested operation */
2816 Fast486FpuArithmeticOperation(State
, ModRegRm
.Register
, &MemoryData
, TRUE
);
2821 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB
)
2823 FAST486_MOD_REG_RM ModRegRm
;
2824 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2826 TOGGLE_ADSIZE(AddressSize
);
2828 /* Get the operands */
2829 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2831 /* Exception occurred */
2837 #ifndef FAST486_NO_FPU
2839 if (ModRegRm
.Memory
)
2841 Fast486FpuExceptionCheck(State
);
2842 FPU_SAVE_LAST_INST();
2843 FPU_SAVE_LAST_OPERAND();
2845 switch (ModRegRm
.Register
)
2851 FAST486_FPU_DATA_REG Temp
;
2853 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, (PULONG
)&Value
))
2855 /* Exception occurred */
2859 Fast486FpuFromInteger(State
, (LONGLONG
)Value
, &Temp
);
2860 Fast486FpuPush(State
, &Temp
);
2872 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL
))
2874 /* Raise the invalid operation exception */
2875 State
->FpuStatus
.Ie
= TRUE
;
2877 if (!State
->FpuControl
.Im
)
2883 if (!Fast486FpuToInteger(State
, &FPU_ST(0), &Temp
))
2885 /* Exception occurred */
2889 /* Check if it can fit in a signed 32-bit integer */
2890 if ((LONGLONG
)((LONG
)Temp
) != Temp
)
2892 State
->FpuStatus
.Ie
= TRUE
;
2894 if (State
->FpuControl
.Im
)
2896 Temp
= 0x80000000LL
;
2904 if (!Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, (ULONG
)((LONG
)Temp
)))
2906 /* Exception occurred */
2910 if (ModRegRm
.Register
== 3)
2912 /* Pop the FPU stack too */
2913 Fast486FpuPop(State
);
2922 FAST486_FPU_DATA_REG Value
;
2925 if (!Fast486ReadMemory(State
,
2926 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
2927 ? State
->SegmentOverride
: FAST486_REG_DS
,
2928 ModRegRm
.MemoryAddress
,
2933 /* Exception occurred */
2937 Value
.Mantissa
= *((PULONGLONG
)Buffer
);
2938 Value
.Exponent
= *((PUSHORT
)&Buffer
[8]) & (FPU_MAX_EXPONENT
+ 1);
2939 Value
.Sign
= *((PUCHAR
)&Buffer
[9]) >> 7;
2941 Fast486FpuPush(State
, &Value
);
2950 if (FPU_GET_TAG(0) != FPU_TAG_EMPTY
)
2952 *((PULONGLONG
)Buffer
) = FPU_ST(0).Mantissa
;
2953 *((PUSHORT
)&Buffer
[sizeof(ULONGLONG
)]) = FPU_ST(0).Exponent
2954 | (FPU_ST(0).Sign
? 0x8000 : 0);
2958 /* Raise the invalid operation exception */
2959 State
->FpuStatus
.Ie
= TRUE
;
2961 if (State
->FpuControl
.Im
)
2963 *((PULONGLONG
)Buffer
) = FPU_INDEFINITE_MANTISSA
;
2964 *((PUSHORT
)&Buffer
[sizeof(ULONGLONG
)]) = 0x8000 | (FPU_MAX_EXPONENT
+ 1);
2972 if (!Fast486WriteMemory(State
,
2973 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
2974 ? State
->SegmentOverride
: FAST486_REG_DS
,
2975 ModRegRm
.MemoryAddress
,
2979 /* Exception occurred */
2983 Fast486FpuPop(State
);
2990 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2997 /* Only a few of these instructions have any meaning on a 487 */
2998 switch ((ModRegRm
.Register
<< 3) | ModRegRm
.SecondRegister
)
3003 /* Clear exception data */
3004 State
->FpuStatus
.Ie
=
3005 State
->FpuStatus
.De
=
3006 State
->FpuStatus
.Ze
=
3007 State
->FpuStatus
.Oe
=
3008 State
->FpuStatus
.Ue
=
3009 State
->FpuStatus
.Pe
=
3010 State
->FpuStatus
.Sf
=
3011 State
->FpuStatus
.Es
=
3012 State
->FpuStatus
.Busy
= FALSE
;
3020 /* Restore the state */
3021 State
->FpuControl
.Value
= FAST486_FPU_DEFAULT_CONTROL
;
3022 State
->FpuStatus
.Value
= 0;
3023 State
->FpuTag
= 0xFFFF;
3037 /* These do nothing */
3044 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
3053 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDC
)
3055 FAST486_MOD_REG_RM ModRegRm
;
3056 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
3057 #ifndef FAST486_NO_FPU
3058 PFAST486_FPU_DATA_REG Operand
;
3059 FAST486_FPU_DATA_REG MemoryData
;
3062 TOGGLE_ADSIZE(AddressSize
);
3064 /* Get the operands */
3065 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3067 /* Exception occurred */
3073 #ifndef FAST486_NO_FPU
3075 Fast486FpuExceptionCheck(State
);
3076 FPU_SAVE_LAST_INST();
3078 if (ModRegRm
.Memory
)
3082 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
3084 /* Raise the invalid operation exception */
3085 State
->FpuStatus
.Ie
= TRUE
;
3087 if (State
->FpuControl
.Im
)
3089 /* Return the indefinite NaN */
3090 FPU_ST(0).Sign
= TRUE
;
3091 FPU_ST(0).Exponent
= FPU_MAX_EXPONENT
+ 1;
3092 FPU_ST(0).Mantissa
= FPU_INDEFINITE_MANTISSA
;
3094 FPU_SET_TAG(0, FPU_TAG_SPECIAL
);
3100 /* Load the source operand from memory */
3101 if (!Fast486ReadMemory(State
,
3102 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
3103 ? State
->SegmentOverride
: FAST486_REG_DS
,
3104 ModRegRm
.MemoryAddress
,
3109 /* Exception occurred */
3113 Fast486FpuFromDoubleReal(State
, Value
, &MemoryData
);
3114 Operand
= &MemoryData
;
3116 FPU_SAVE_LAST_OPERAND();
3120 /* Load the destination operand from an FPU register */
3121 Operand
= &FPU_ST(ModRegRm
.SecondRegister
);
3123 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
3124 || (FPU_GET_TAG(ModRegRm
.SecondRegister
) == FPU_TAG_EMPTY
))
3126 /* Raise the invalid operation exception */
3127 State
->FpuStatus
.Ie
= TRUE
;
3129 if (State
->FpuControl
.Im
)
3131 /* Return the indefinite NaN */
3132 Operand
->Sign
= TRUE
;
3133 Operand
->Exponent
= FPU_MAX_EXPONENT
+ 1;
3134 Operand
->Mantissa
= FPU_INDEFINITE_MANTISSA
;
3136 FPU_SET_TAG(ModRegRm
.SecondRegister
, FPU_TAG_SPECIAL
);
3143 /* Perform the requested operation */
3144 Fast486FpuArithmeticOperation(State
, ModRegRm
.Register
, Operand
, ModRegRm
.Memory
);
3149 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDD
)
3151 FAST486_MOD_REG_RM ModRegRm
;
3152 BOOLEAN OperandSize
, AddressSize
;
3154 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
3155 TOGGLE_OPSIZE(OperandSize
);
3156 TOGGLE_ADSIZE(AddressSize
);
3158 /* Get the operands */
3159 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3161 /* Exception occurred */
3167 #ifndef FAST486_NO_FPU
3169 if (ModRegRm
.Memory
)
3171 switch (ModRegRm
.Register
)
3177 FAST486_FPU_DATA_REG MemoryData
;
3179 Fast486FpuExceptionCheck(State
);
3180 FPU_SAVE_LAST_INST();
3181 FPU_SAVE_LAST_OPERAND();
3183 if (!Fast486ReadMemory(State
,
3184 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
3185 ? State
->SegmentOverride
: FAST486_REG_DS
,
3186 ModRegRm
.MemoryAddress
,
3191 /* Exception occurred */
3195 Fast486FpuFromDoubleReal(State
, Value
, &MemoryData
);
3196 Fast486FpuPush(State
, &MemoryData
);
3206 ULONGLONG Value
= FPU_REAL8_INDEFINITE
;
3208 Fast486FpuExceptionCheck(State
);
3209 FPU_SAVE_LAST_INST();
3210 FPU_SAVE_LAST_OPERAND();
3212 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
3214 /* Raise the invalid operation exception */
3215 State
->FpuStatus
.Ie
= TRUE
;
3217 if (!State
->FpuControl
.Im
)
3222 else if (!Fast486FpuToDoubleReal(State
, &FPU_ST(0), &Value
))
3224 /* Exception occurred */
3228 if (!Fast486WriteMemory(State
,
3229 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
3230 ? State
->SegmentOverride
: FAST486_REG_DS
,
3231 ModRegRm
.MemoryAddress
,
3235 /* Exception occurred */
3239 if (ModRegRm
.Register
== 3) Fast486FpuPop(State
);
3249 /* Save the environment */
3250 if (!Fast486FpuLoadEnvironment(State
,
3251 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
3252 ? State
->SegmentOverride
: FAST486_REG_DS
,
3253 ModRegRm
.MemoryAddress
,
3256 /* Exception occurred */
3260 /* Load the registers */
3261 if (!Fast486ReadMemory(State
,
3262 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
3263 ? State
->SegmentOverride
: FAST486_REG_DS
,
3264 ModRegRm
.MemoryAddress
+ (OperandSize
+ 1) * 14,
3269 /* Exception occurred */
3273 for (i
= 0; i
< FAST486_NUM_FPU_REGS
; i
++)
3275 State
->FpuRegisters
[i
].Mantissa
= *((PULONGLONG
)&AllRegs
[i
* 10]);
3276 State
->FpuRegisters
[i
].Exponent
= *((PUSHORT
)&AllRegs
[(i
* 10) + sizeof(ULONGLONG
)]) & 0x7FFF;
3278 if (*((PUSHORT
)&AllRegs
[(i
* 10) + sizeof(ULONGLONG
)]) & 0x8000)
3280 State
->FpuRegisters
[i
].Sign
= TRUE
;
3284 State
->FpuRegisters
[i
].Sign
= FALSE
;
3297 /* Save the environment */
3298 if (!Fast486FpuSaveEnvironment(State
,
3299 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
3300 ? State
->SegmentOverride
: FAST486_REG_DS
,
3301 ModRegRm
.MemoryAddress
,
3304 /* Exception occurred */
3308 /* Save the registers */
3309 for (i
= 0; i
< FAST486_NUM_FPU_REGS
; i
++)
3311 *((PULONGLONG
)&AllRegs
[i
* 10]) = State
->FpuRegisters
[i
].Mantissa
;
3312 *((PUSHORT
)&AllRegs
[(i
* 10) + sizeof(ULONGLONG
)]) = State
->FpuRegisters
[i
].Exponent
;
3314 if (State
->FpuRegisters
[i
].Sign
)
3316 *((PUSHORT
)&AllRegs
[(i
* 10) + sizeof(ULONGLONG
)]) |= 0x8000;
3320 Fast486WriteMemory(State
,
3321 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
3322 ? State
->SegmentOverride
: FAST486_REG_DS
,
3323 ModRegRm
.MemoryAddress
+ (OperandSize
+ 1) * 14,
3333 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, State
->FpuStatus
.Value
);
3340 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
3346 switch (ModRegRm
.Register
)
3351 FPU_SET_TAG(ModRegRm
.SecondRegister
, FPU_TAG_EMPTY
);
3358 FAST486_FPU_DATA_REG Temp
;
3360 FPU_SAVE_LAST_INST();
3361 Fast486FpuExceptionCheck(State
);
3363 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
3364 || FPU_GET_TAG(ModRegRm
.SecondRegister
) == FPU_TAG_EMPTY
)
3366 State
->FpuStatus
.Ie
= TRUE
;
3372 FPU_ST(0) = FPU_ST(ModRegRm
.SecondRegister
);
3373 FPU_ST(ModRegRm
.SecondRegister
) = Temp
;
3376 FPU_UPDATE_TAG(ModRegRm
.SecondRegister
);
3386 FPU_SAVE_LAST_INST();
3387 Fast486FpuExceptionCheck(State
);
3389 FPU_ST(ModRegRm
.SecondRegister
) = FPU_ST(0);
3390 FPU_UPDATE_TAG(ModRegRm
.SecondRegister
);
3392 if (ModRegRm
.Register
== 3) Fast486FpuPop(State
);
3401 FPU_SAVE_LAST_INST();
3402 Fast486FpuExceptionCheck(State
);
3404 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
3405 || (FPU_GET_TAG(ModRegRm
.SecondRegister
) == FPU_TAG_EMPTY
))
3407 State
->FpuStatus
.Ie
= TRUE
;
3411 Fast486FpuCompare(State
, &FPU_ST(0), &FPU_ST(ModRegRm
.SecondRegister
));
3412 if (ModRegRm
.Register
== 5) Fast486FpuPop(State
);
3420 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
3428 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDE
)
3430 FAST486_MOD_REG_RM ModRegRm
;
3431 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
3432 #ifndef FAST486_NO_FPU
3433 PFAST486_FPU_DATA_REG Operand
;
3434 FAST486_FPU_DATA_REG MemoryData
;
3437 TOGGLE_ADSIZE(AddressSize
);
3439 /* Get the operands */
3440 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3442 /* Exception occurred */
3448 #ifndef FAST486_NO_FPU
3450 FPU_SAVE_LAST_INST();
3451 Fast486FpuExceptionCheck(State
);
3453 if (ModRegRm
.Memory
)
3457 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
3459 /* Raise the invalid operation exception */
3460 State
->FpuStatus
.Ie
= TRUE
;
3462 if (State
->FpuControl
.Im
)
3464 /* Return the indefinite NaN */
3465 FPU_ST(0).Sign
= TRUE
;
3466 FPU_ST(0).Exponent
= FPU_MAX_EXPONENT
+ 1;
3467 FPU_ST(0).Mantissa
= FPU_INDEFINITE_MANTISSA
;
3469 FPU_SET_TAG(0, FPU_TAG_SPECIAL
);
3475 /* Load the source operand from memory */
3476 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, (PUSHORT
)&Value
))
3478 /* Exception occurred */
3482 Fast486FpuFromInteger(State
, (LONGLONG
)Value
, &MemoryData
);
3483 Operand
= &MemoryData
;
3485 FPU_SAVE_LAST_OPERAND();
3490 if ((ModRegRm
.Register
== 3) && (ModRegRm
.SecondRegister
!= 1))
3493 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
3497 /* Load the destination operand from a register */
3498 Operand
= &FPU_ST(ModRegRm
.SecondRegister
);
3500 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
3501 || (FPU_GET_TAG(ModRegRm
.SecondRegister
) == FPU_TAG_EMPTY
))
3503 /* Raise the invalid operation exception, if unmasked */
3504 State
->FpuStatus
.Ie
= TRUE
;
3509 /* Perform the requested operation */
3510 Fast486FpuArithmeticOperation(State
, ModRegRm
.Register
, Operand
, ModRegRm
.Memory
);
3511 if (!ModRegRm
.Memory
) Fast486FpuPop(State
);
3516 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF
)
3518 FAST486_MOD_REG_RM ModRegRm
;
3519 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
3521 TOGGLE_ADSIZE(AddressSize
);
3523 /* Get the operands */
3524 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3526 /* Exception occurred */
3532 #ifndef FAST486_NO_FPU
3534 FPU_SAVE_LAST_INST();
3535 Fast486FpuExceptionCheck(State
);
3537 if (ModRegRm
.Memory
)
3539 FPU_SAVE_LAST_OPERAND();
3541 switch (ModRegRm
.Register
)
3547 FAST486_FPU_DATA_REG Temp
;
3549 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, (PUSHORT
)&Value
))
3551 /* Exception occurred */
3555 Fast486FpuFromInteger(State
, (LONGLONG
)Value
, &Temp
);
3556 Fast486FpuPush(State
, &Temp
);
3566 LONGLONG Temp
= 0LL;
3568 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL
))
3570 /* Raise the invalid operation exception */
3571 State
->FpuStatus
.Ie
= TRUE
;
3573 if (!State
->FpuControl
.Im
)
3579 if (!Fast486FpuToInteger(State
, &FPU_ST(0), &Temp
))
3581 /* Exception occurred */
3585 /* Check if it can fit in a signed 16-bit integer */
3586 if ((LONGLONG
)((SHORT
)Temp
) != Temp
)
3588 /* Raise the invalid operation exception */
3589 State
->FpuStatus
.Ie
= TRUE
;
3591 if (State
->FpuControl
.Im
)
3601 if (!Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, (USHORT
)((SHORT
)Temp
)))
3603 /* Exception occurred */
3607 if (ModRegRm
.Register
== 3)
3609 /* Pop the FPU stack too */
3610 Fast486FpuPop(State
);
3619 FAST486_FPU_DATA_REG Value
;
3622 if (!Fast486ReadMemory(State
,
3623 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
3624 ? State
->SegmentOverride
: FAST486_REG_DS
,
3625 ModRegRm
.MemoryAddress
,
3630 /* Exception occurred */
3634 Fast486FpuFromPackedBcd(State
, Buffer
, &Value
);
3635 Fast486FpuPush(State
, &Value
);
3640 /* FILD (64-bit int) */
3644 FAST486_FPU_DATA_REG Temp
;
3646 if (!Fast486ReadMemory(State
,
3647 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
3648 ? State
->SegmentOverride
: FAST486_REG_DS
,
3649 ModRegRm
.MemoryAddress
,
3654 /* Exception occurred */
3658 Fast486FpuFromInteger(State
, (LONGLONG
)Value
, &Temp
);
3659 Fast486FpuPush(State
, &Temp
);
3667 UCHAR Buffer
[10] = {0};
3669 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
3671 /* Raise the invalid operation exception */
3672 State
->FpuStatus
.Ie
= TRUE
;
3674 if (!State
->FpuControl
.Im
)
3679 else if (!Fast486FpuToPackedBcd(State
, &FPU_ST(0), Buffer
))
3681 /* Exception occurred */
3685 if (!Fast486WriteMemory(State
,
3686 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
3687 ? State
->SegmentOverride
: FAST486_REG_DS
,
3688 ModRegRm
.MemoryAddress
,
3692 /* Exception occurred */
3696 Fast486FpuPop(State
);
3700 /* FISTP (64-bit int) */
3703 LONGLONG Temp
= 0LL;
3705 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL
))
3707 /* Raise the invalid operation exception */
3708 State
->FpuStatus
.Ie
= TRUE
;
3710 if (!State
->FpuControl
.Im
)
3716 if (!Fast486FpuToInteger(State
, &FPU_ST(0), &Temp
))
3718 /* Exception occurred */
3722 if (!Fast486WriteMemory(State
,
3723 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
3724 ? State
->SegmentOverride
: FAST486_REG_DS
,
3725 ModRegRm
.MemoryAddress
,
3729 /* Exception occurred */
3733 /* Pop the FPU stack too */
3734 Fast486FpuPop(State
);
3742 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
3748 switch (ModRegRm
.Register
)
3753 FPU_SET_TAG(ModRegRm
.SecondRegister
, FPU_TAG_EMPTY
);
3754 Fast486FpuPop(State
);
3762 FAST486_FPU_DATA_REG Temp
;
3764 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
3765 || FPU_GET_TAG(ModRegRm
.SecondRegister
) == FPU_TAG_EMPTY
)
3767 State
->FpuStatus
.Ie
= TRUE
;
3773 FPU_ST(0) = FPU_ST(ModRegRm
.SecondRegister
);
3774 FPU_ST(ModRegRm
.SecondRegister
) = Temp
;
3777 FPU_UPDATE_TAG(ModRegRm
.SecondRegister
);
3786 FPU_ST(ModRegRm
.SecondRegister
) = FPU_ST(0);
3787 FPU_UPDATE_TAG(ModRegRm
.SecondRegister
);
3788 Fast486FpuPop(State
);
3796 if (ModRegRm
.SecondRegister
!= 0)
3799 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
3803 /* Store the status word in AX */
3804 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= State
->FpuStatus
.Value
;
3812 Fast486Exception(State
, FAST486_EXCEPTION_UD
);