ReactOS  0.4.13-dev-73-gcfe54aa
fpu.c
Go to the documentation of this file.
1 /*
2  * Fast486 386/486 CPU Emulation Library
3  * fpu.c
4  *
5  * Copyright (C) 2015 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
6  *
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.
11  *
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.
16  *
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.
20  */
21 
22 /* INCLUDES *******************************************************************/
23 
24 #include <windef.h>
25 
26 // #define NDEBUG
27 #include <debug.h>
28 
29 #include <fast486.h>
30 #include "common.h"
31 #include "fpu.h"
32 
33 /* CONSTANTS ******************************************************************/
34 
35 /* 0.00 */
36 static const FAST486_FPU_DATA_REG FpuZero = {0ULL, 0, FALSE};
37 
38 /* 1.00 */
39 static const FAST486_FPU_DATA_REG FpuOne = {0x8000000000000000ULL, FPU_REAL10_BIAS, FALSE};
40 
41 /* Pi */
42 static const FAST486_FPU_DATA_REG FpuPi = {0xC90FDAA22168C235ULL, FPU_REAL10_BIAS + 1, FALSE};
43 
44 /* lb(10) */
45 static const FAST486_FPU_DATA_REG FpuL2Ten = {0xD49A784BCD1B8AFEULL, FPU_REAL10_BIAS + 1, FALSE};
46 
47 /* lb(e) */
48 static const FAST486_FPU_DATA_REG FpuL2E = {0xB8AA3B295C17F0BCULL, FPU_REAL10_BIAS, FALSE};
49 
50 /* lg(2) */
51 static const FAST486_FPU_DATA_REG FpuLgTwo = {0x9A209A84FBCFF799ULL, FPU_REAL10_BIAS - 2, FALSE};
52 
53 /* ln(2) */
54 static const FAST486_FPU_DATA_REG FpuLnTwo = {0xB17217F7D1CF79ACULL, FPU_REAL10_BIAS - 1, FALSE};
55 
56 /* 2.00 */
57 static const FAST486_FPU_DATA_REG FpuTwo = {0x8000000000000000ULL, FPU_REAL10_BIAS + 1, FALSE};
58 
59 /* Pi / 2 */
60 static const FAST486_FPU_DATA_REG FpuHalfPi = {0xC90FDAA22168C235ULL, FPU_REAL10_BIAS, FALSE};
61 
62 static const FAST486_FPU_DATA_REG FpuInverseNumber[INVERSE_NUMBERS_COUNT] =
63 {
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 */
114 };
115 
116 static const FAST486_FPU_DATA_REG FpuInverseNumberSine[INVERSE_NUMBERS_COUNT] =
117 {
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 */
168 };
169 
170 static const FAST486_FPU_DATA_REG FpuInverseNumberCosine[INVERSE_NUMBERS_COUNT] =
171 {
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 */
222 };
223 
224 static const FAST486_FPU_DATA_REG FpuInverseNumberAtan[INVERSE_NUMBERS_COUNT] =
225 {
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 */
276 };
277 
278 /* PRIVATE FUNCTIONS **********************************************************/
279 
280 #ifndef FAST486_NO_FPU
281 
282 static ULONGLONG
284  ULONGLONG Multiplier,
285  ULONGLONG *HighProduct)
286 {
287  ULONG MultiplicandLow, MultiplicandHigh, MultiplierLow, MultiplierHigh;
288  ULONG IntermediateLow, IntermediateHigh;
289  ULONGLONG LowProduct, Intermediate, Intermediate1, Intermediate2;
290 
291  MultiplicandLow = (ULONG)(Multiplicand & 0xFFFFFFFFULL);
292  MultiplicandHigh = (ULONG)(Multiplicand >> 32);
293  MultiplierLow = (ULONG)(Multiplier & 0xFFFFFFFFULL);
294  MultiplierHigh = (ULONG)(Multiplier >> 32);
295 
296  LowProduct = (ULONGLONG)MultiplicandLow * (ULONGLONG)MultiplierLow;
297  Intermediate1 = (ULONGLONG)MultiplicandLow * (ULONGLONG)MultiplierHigh;
298  Intermediate2 = (ULONGLONG)MultiplicandHigh * (ULONGLONG)MultiplierLow;
299  *HighProduct = (ULONGLONG)MultiplicandHigh * (ULONGLONG)MultiplierHigh;
300 
301  Intermediate = Intermediate1 + Intermediate2;
302  if (Intermediate < Intermediate1) *HighProduct += 1ULL << 32;
303 
304  IntermediateLow = (ULONG)(Intermediate & 0xFFFFFFFFULL);
305  IntermediateHigh = (ULONG)(Intermediate >> 32);
306 
307  LowProduct += (ULONGLONG)IntermediateLow << 32;
308  if ((ULONG)(LowProduct >> 32) < IntermediateLow) (*HighProduct)++;
309 
310  *HighProduct += IntermediateHigh;
311  return LowProduct;
312 }
313 
314 static ULONGLONG
316  ULONGLONG DividendHigh,
318  PULONGLONG QuotientLow,
319  PULONGLONG QuotientHigh)
320 {
321  ULONGLONG ValueLow = DividendLow;
322  ULONGLONG ValueHigh = DividendHigh;
323  ULONGLONG CurrentLow = 0ULL;
324  ULONGLONG CurrentHigh = Divisor;
325  ULONG Bits;
326 
327  ASSERT(Divisor != 0ULL);
328 
329  /* Initialize the quotient */
330  *QuotientLow = *QuotientHigh = 0ULL;
331 
332  /* Exit early if the dividend is lower than the divisor */
333  if ((DividendHigh == 0ULL) && (DividendLow < Divisor)) return ValueLow;
334 
335  /* Normalize the current divisor */
336  Bits = CountLeadingZeros64(CurrentHigh);
337  CurrentHigh <<= Bits;
338 
339  while (TRUE)
340  {
341  /* Shift the quotient left by one bit */
342  *QuotientHigh <<= 1;
343  *QuotientHigh |= *QuotientLow >> 63;
344  *QuotientLow <<= 1;
345 
346  /* Check if the value is higher than or equal to the current divisor */
347  if ((ValueHigh > CurrentHigh)
348  || ((ValueHigh == CurrentHigh) && (ValueLow >= CurrentLow)))
349  {
350  BOOLEAN Carry = ValueLow < CurrentLow;
351 
352  /* Subtract the current divisor from the value */
353  ValueHigh -= CurrentHigh;
354  ValueLow -= CurrentLow;
355  if (Carry) ValueHigh--;
356 
357  /* Set the lowest bit of the quotient */
358  *QuotientLow |= 1;
359 
360  /* Stop if the value is lower than the original divisor */
361  if ((ValueHigh == 0ULL) && (ValueLow < Divisor)) break;
362  }
363 
364  /* Shift the current divisor right by one bit */
365  CurrentLow >>= 1;
366  CurrentLow |= (CurrentHigh & 1) << 63;
367  CurrentHigh >>= 1;
368  }
369 
370  /*
371  * Calculate the number of significant bits the current
372  * divisor has more than the original divisor
373  */
374  Bits = CountLeadingZeros64(Divisor);
375  if (CurrentHigh > 0ULL) Bits += 64 - CountLeadingZeros64(CurrentHigh);
376  else Bits -= CountLeadingZeros64(CurrentLow);
377 
378  if (Bits >= 64)
379  {
380  *QuotientHigh = *QuotientLow;
381  *QuotientLow = 0ULL;
382  Bits -= 64;
383  }
384 
385  if (Bits)
386  {
387  /* Shift the quotient left by that amount */
388  *QuotientHigh <<= Bits;
389  *QuotientHigh |= *QuotientLow >> (64 - Bits);
390  *QuotientLow <<= Bits;
391  }
392 
393  /* Return the remainder */
394  return ValueLow;
395 }
396 
397 static inline VOID FASTCALL
398 Fast486FpuRound(PFAST486_STATE State,
400  BOOLEAN Sign,
402  INT RemainderHighBit)
403 {
404  switch (State->FpuControl.Rc)
405  {
406  case FPU_ROUND_NEAREST:
407  {
408  /* Check if the highest bit of the remainder is set */
409  if (Remainder & (1ULL << RemainderHighBit))
410  {
411  (*Result)++;
412 
413  /* Check if all the other bits are clear */
414  if (!(Remainder & ((1ULL << RemainderHighBit) - 1ULL)))
415  {
416  /* Round to even */
417  *Result &= ~1ULL;
418  }
419  }
420 
421  break;
422  }
423 
424  case FPU_ROUND_DOWN:
425  {
426  if ((Remainder != 0ULL) && Sign) (*Result)++;
427  break;
428  }
429 
430  case FPU_ROUND_UP:
431  {
432  if ((Remainder != 0ULL) && !Sign) (*Result)++;
433  break;
434  }
435 
436  default:
437  {
438  /* Leave it truncated */
439  }
440  }
441 }
442 
443 static inline VOID FASTCALL
445  LONGLONG Value,
446  PFAST486_FPU_DATA_REG Result)
447 {
448  ULONG ZeroCount;
449 
450  Result->Sign = Result->Exponent = Result->Mantissa = 0;
451  if (Value == 0LL) return;
452 
453  if (Value < 0LL)
454  {
455  Result->Sign = TRUE;
456  Value = -Value;
457  }
458 
459  Result->Mantissa = (ULONGLONG)Value;
460  ZeroCount = CountLeadingZeros64(Result->Mantissa);
461 
462  Result->Mantissa <<= ZeroCount;
463  Result->Exponent = FPU_REAL10_BIAS + 63 - ZeroCount;
464 }
465 
466 static inline BOOLEAN FASTCALL
467 Fast486FpuToInteger(PFAST486_STATE State,
468  PCFAST486_FPU_DATA_REG Value,
470 {
471  ULONG Bits;
473  SHORT UnbiasedExp = (SHORT)Value->Exponent - FPU_REAL10_BIAS;
474 
475  if (FPU_IS_ZERO(Value))
476  {
477  *Result = 0LL;
478  return TRUE;
479  }
480 
481  if (FPU_IS_NAN(Value) || !FPU_IS_NORMALIZED(Value) || (UnbiasedExp >= 63))
482  {
483  /* Raise an invalid operation exception */
484  State->FpuStatus.Ie = TRUE;
485 
486  if (State->FpuControl.Im)
487  {
488  *Result = 0x8000000000000000LL;
489  return TRUE;
490  }
491  else
492  {
493  return FALSE;
494  }
495  }
496 
497  if (UnbiasedExp >= 0)
498  {
499  Bits = 63 - UnbiasedExp;
500 
501  /* Calculate the result and the remainder */
502  *Result = (LONGLONG)(Value->Mantissa >> Bits);
503  Remainder = Value->Mantissa & ((1ULL << Bits) - 1);
504  }
505  else
506  {
507  /* The result is zero */
508  *Result = 0LL;
509  Bits = 64;
510 
511  if (UnbiasedExp >= -64)
512  {
513  Remainder = Value->Mantissa >> (-1 - UnbiasedExp);
514  }
515  else
516  {
517  /* Too small to even have a remainder */
518  Remainder = 0ULL;
519  }
520  }
521 
522  /* The result must be positive here */
523  ASSERT(*Result >= 0LL);
524 
525  /* Perform rounding */
526  Fast486FpuRound(State, (PULONGLONG)Result, Value->Sign, Remainder, Bits - 1);
527 
528  if (Value->Sign) *Result = -*Result;
529  return TRUE;
530 }
531 
532 static inline VOID FASTCALL
534  ULONG Value,
535  PFAST486_FPU_DATA_REG Result)
536 {
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;
541 
542  /* If this is a zero, we're done */
543  if (Value == 0) return;
544 
545  if (Result->Exponent == 0xFF) Result->Exponent = FPU_MAX_EXPONENT + 1;
546  else
547  {
548  /* Adjust the exponent bias */
549  Result->Exponent += (FPU_REAL10_BIAS - FPU_REAL4_BIAS);
550  }
551 }
552 
553 static inline BOOLEAN FASTCALL
555  PCFAST486_FPU_DATA_REG Value,
556  PULONG Result)
557 {
559  SHORT UnbiasedExp = (SHORT)Value->Exponent - FPU_REAL10_BIAS;
560  ULONGLONG Result64;
561 
562  if (FPU_IS_ZERO(Value))
563  {
564  *Result = 0;
565  return TRUE;
566  }
567 
568  /* Calculate the mantissa */
569  *Result = (ULONG)(Value->Mantissa >> 40) & 0x7FFFFF;
570 
571  if (FPU_IS_NAN(Value))
572  {
574  goto SetSign;
575  }
576 
577  /* Check for underflow */
578  if (!FPU_IS_NORMALIZED(Value) || (UnbiasedExp < -127))
579  {
580  /* Raise the underflow exception */
581  State->FpuStatus.Ue = TRUE;
582 
583  if (State->FpuControl.Um)
584  {
585  /* The result is zero due to underflow */
586  *Result = 0ULL;
587  return TRUE;
588  }
589  else
590  {
591  return FALSE;
592  }
593  }
594 
595  /* Check for overflow */
596  if (UnbiasedExp > 127)
597  {
598  /* Raise the overflow exception */
599  State->FpuStatus.Oe = TRUE;
600 
601  if (State->FpuControl.Om)
602  {
603  /* The result is infinity due to overflow */
605  goto SetSign;
606  }
607  else
608  {
609  return FALSE;
610  }
611  }
612 
613  /* Calculate the remainder */
614  Remainder = Value->Mantissa & ((1ULL << 40) - 1);
615 
616  /* Store the biased exponent */
617  *Result |= (ULONG)(UnbiasedExp + FPU_REAL4_BIAS) << 23;
618 
619  /* Perform rounding */
620  Result64 = (ULONGLONG)*Result;
621  Fast486FpuRound(State, &Result64, Value->Sign, Remainder, 39);
622  *Result = (ULONG)Result64;
623 
624 SetSign:
625 
626  if (Value->Sign) *Result |= 0x80000000;
627  return TRUE;
628 }
629 
630 static inline VOID FASTCALL
633  PFAST486_FPU_DATA_REG Result)
634 {
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;
639 
640  /* If this is a zero, we're done */
641  if (Value == 0) return;
642 
643  if (Result->Exponent == 0x7FF) Result->Exponent = FPU_MAX_EXPONENT + 1;
644  else
645  {
646  /* Adjust the exponent bias */
647  Result->Exponent += (FPU_REAL10_BIAS - FPU_REAL8_BIAS);
648  }
649 }
650 
651 static inline BOOLEAN FASTCALL
653  PCFAST486_FPU_DATA_REG Value,
655 {
657  SHORT UnbiasedExp = (SHORT)Value->Exponent - FPU_REAL10_BIAS;
658 
659  if (FPU_IS_ZERO(Value))
660  {
661  *Result = 0LL;
662  return TRUE;
663  }
664 
665  /* Calculate the mantissa */
666  *Result = (Value->Mantissa >> 11) & ((1ULL << 52) - 1);
667 
668  if (FPU_IS_NAN(Value))
669  {
671  goto SetSign;
672  }
673 
674  /* Check for underflow */
675  if (!FPU_IS_NORMALIZED(Value) || (UnbiasedExp < -1023))
676  {
677  /* Raise the underflow exception */
678  State->FpuStatus.Ue = TRUE;
679 
680  if (State->FpuControl.Um)
681  {
682  /* The result is zero due to underflow */
683  *Result = 0ULL;
684  return TRUE;
685  }
686  else
687  {
688  return FALSE;
689  }
690  }
691 
692  /* Check for overflow */
693  if (UnbiasedExp > 1023)
694  {
695  /* Raise the overflow exception */
696  State->FpuStatus.Oe = TRUE;
697 
698  if (State->FpuControl.Om)
699  {
700  /* The result is infinity due to overflow */
702  goto SetSign;
703  }
704  else
705  {
706  return FALSE;
707  }
708  }
709 
710  /* Calculate the remainder */
711  Remainder = Value->Mantissa & ((1ULL << 11) - 1ULL);
712 
713  /* Store the biased exponent */
714  *Result |= (ULONGLONG)(UnbiasedExp + FPU_REAL8_BIAS) << 52;
715 
716  /* Perform rounding */
718 
719 SetSign:
720 
721  if (Value->Sign) *Result |= 1ULL << 63;
722  return TRUE;
723 }
724 
725 static inline VOID FASTCALL
727  PUCHAR Value,
728  PFAST486_FPU_DATA_REG Result)
729 {
730  INT i;
731  LONGLONG IntVal = 0LL;
732 
733  for (i = 8; i >= 0; i--)
734  {
735  IntVal *= 100LL;
736  IntVal += (Value[i] >> 4) * 10 + (Value[i] & 0x0F);
737  }
738 
739  /* Apply the sign */
740  if (Value[9] & 0x80) IntVal = -IntVal;
741 
742  /* Now convert the integer to FP80 */
744 }
745 
746 static inline BOOLEAN FASTCALL
748  PCFAST486_FPU_DATA_REG Value,
749  PUCHAR Result)
750 {
751  INT i;
752  LONGLONG IntVal;
753 
754  /* Convert it to an integer first */
755  if (!Fast486FpuToInteger(State, Value, &IntVal)) return FALSE;
756 
757  if (IntVal < 0LL)
758  {
759  IntVal = -IntVal;
760  Result[9] = 0x80;
761  }
762 
763  for (i = 0; i < 9; i++)
764  {
765  Result[i] = (UCHAR)((IntVal % 10) + (((IntVal / 10) % 10) << 4));
766  IntVal /= 100LL;
767  }
768 
769  return TRUE;
770 }
771 
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)
777 {
778  FAST486_FPU_DATA_REG FirstAdjusted = *FirstOperand;
779  FAST486_FPU_DATA_REG SecondAdjusted = *SecondOperand;
780  FAST486_FPU_DATA_REG TempResult;
781 
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)))
786  {
787  /* The result will be indefinite */
788  Result->Sign = TRUE;
789  Result->Exponent = FPU_MAX_EXPONENT + 1;
790  Result->Mantissa = FPU_INDEFINITE_MANTISSA;
791  return TRUE;
792  }
793 
794  if ((!FPU_IS_NORMALIZED(FirstOperand) || !FPU_IS_NORMALIZED(SecondOperand)))
795  {
796  /* Raise the denormalized exception */
797  State->FpuStatus.De = TRUE;
798 
799  if (!State->FpuControl.Dm)
800  {
801  return FALSE;
802  }
803  }
804 
805  if (FPU_IS_ZERO(FirstOperand) || FPU_IS_INFINITY(SecondOperand))
806  {
807  /* The second operand is the result */
808  *Result = *SecondOperand;
809  return TRUE;
810  }
811 
812  if (FPU_IS_ZERO(SecondOperand) || FPU_IS_INFINITY(FirstOperand))
813  {
814  /* The first operand is the result */
815  *Result = *FirstOperand;
816  return TRUE;
817  }
818 
819  /* Find the largest exponent */
820  TempResult.Exponent = max(FirstOperand->Exponent, SecondOperand->Exponent);
821 
822  /* Adjust the first operand to it... */
823  if (FirstAdjusted.Exponent < TempResult.Exponent)
824  {
825  if ((TempResult.Exponent - FirstAdjusted.Exponent) < 64)
826  {
827  FirstAdjusted.Mantissa >>= (TempResult.Exponent - FirstAdjusted.Exponent);
828  FirstAdjusted.Exponent = TempResult.Exponent;
829  }
830  else
831  {
832  /* The second operand is the result */
833  *Result = *SecondOperand;
834  return TRUE;
835  }
836  }
837 
838  /* ... and the second one too */
839  if (SecondAdjusted.Exponent < TempResult.Exponent)
840  {
841  if ((TempResult.Exponent - SecondAdjusted.Exponent) < 64)
842  {
843  SecondAdjusted.Mantissa >>= (TempResult.Exponent - SecondAdjusted.Exponent);
844  SecondAdjusted.Exponent = TempResult.Exponent;
845  }
846  else
847  {
848  /* The first operand is the result */
849  *Result = *FirstOperand;
850  return TRUE;
851  }
852  }
853 
854  if (FirstAdjusted.Sign == SecondAdjusted.Sign)
855  {
856  /* Calculate the mantissa and sign of the result */
857  TempResult.Mantissa = FirstAdjusted.Mantissa + SecondAdjusted.Mantissa;
858  TempResult.Sign = FirstAdjusted.Sign;
859  }
860  else
861  {
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;
866 
867  /* Invert the negative mantissa */
868  if (FirstAdjusted.Sign) FirstAdjusted.Mantissa = -(LONGLONG)FirstAdjusted.Mantissa;
869  if (SecondAdjusted.Sign) SecondAdjusted.Mantissa = -(LONGLONG)SecondAdjusted.Mantissa;
870 
871  /* Calculate the mantissa of the result */
872  TempResult.Mantissa = FirstAdjusted.Mantissa + SecondAdjusted.Mantissa;
873  }
874 
875  /* Did it overflow? */
876  if (FirstAdjusted.Sign == SecondAdjusted.Sign)
877  {
878  if (TempResult.Mantissa < FirstAdjusted.Mantissa
879  || TempResult.Mantissa < SecondAdjusted.Mantissa)
880  {
881  if (TempResult.Exponent == FPU_MAX_EXPONENT)
882  {
883  /* Raise the overflow exception */
884  State->FpuStatus.Oe = TRUE;
885 
886  if (State->FpuControl.Om)
887  {
888  /* Total overflow, return infinity */
889  TempResult.Mantissa = FPU_MANTISSA_HIGH_BIT;
890  TempResult.Exponent = FPU_MAX_EXPONENT + 1;
891  }
892  else
893  {
894  return FALSE;
895  }
896  }
897  else
898  {
899  /* Lose the LSB in favor of the carry */
900  TempResult.Mantissa >>= 1;
901  TempResult.Mantissa |= FPU_MANTISSA_HIGH_BIT;
902  TempResult.Exponent++;
903  }
904  }
905  }
906  else
907  {
908  if (TempResult.Mantissa >= FirstAdjusted.Mantissa
909  && TempResult.Mantissa >= SecondAdjusted.Mantissa)
910  {
911  /* Reverse the mantissa */
912  TempResult.Mantissa = -(LONGLONG)TempResult.Mantissa;
913  }
914  }
915 
916  /* Normalize the result and return it */
917  if (!Fast486FpuNormalize(State, &TempResult))
918  {
919  /* Exception occurred */
920  return FALSE;
921  }
922 
923  *Result = TempResult;
924  return TRUE;
925 }
926 
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)
932 {
933  FAST486_FPU_DATA_REG NegativeSecondOperand = *SecondOperand;
934 
935  /* Invert the sign */
936  NegativeSecondOperand.Sign = !NegativeSecondOperand.Sign;
937 
938  /* And perform an addition instead */
939  return Fast486FpuAdd(State, FirstOperand, &NegativeSecondOperand, Result);
940 }
941 
942 static inline VOID FASTCALL
943 Fast486FpuCompare(PFAST486_STATE State,
944  PCFAST486_FPU_DATA_REG FirstOperand,
945  PCFAST486_FPU_DATA_REG SecondOperand)
946 {
947  if (FPU_IS_NAN(FirstOperand) || FPU_IS_NAN(SecondOperand))
948  {
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)))
952  {
953  State->FpuStatus.Code0 = FALSE;
954  State->FpuStatus.Code2 = FALSE;
955  State->FpuStatus.Code3 = FALSE;
956  }
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)))
960  {
961  State->FpuStatus.Code0 = TRUE;
962  State->FpuStatus.Code2 = FALSE;
963  State->FpuStatus.Code3 = FALSE;
964  }
965  else
966  {
967  State->FpuStatus.Code0 = TRUE;
968  State->FpuStatus.Code2 = TRUE;
969  State->FpuStatus.Code3 = TRUE;
970  }
971  }
972  else
973  {
974  FAST486_FPU_DATA_REG TempResult;
975 
976  Fast486FpuSubtract(State, FirstOperand, SecondOperand, &TempResult);
977 
978  if (FPU_IS_ZERO(&TempResult))
979  {
980  State->FpuStatus.Code0 = FALSE;
981  State->FpuStatus.Code2 = FALSE;
982  State->FpuStatus.Code3 = TRUE;
983  }
984  else if (TempResult.Sign)
985  {
986  State->FpuStatus.Code0 = TRUE;
987  State->FpuStatus.Code2 = FALSE;
988  State->FpuStatus.Code3 = FALSE;
989  }
990  else
991  {
992  State->FpuStatus.Code0 = FALSE;
993  State->FpuStatus.Code2 = FALSE;
994  State->FpuStatus.Code3 = FALSE;
995  }
996  }
997 }
998 
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)
1004 {
1005  FAST486_FPU_DATA_REG TempResult;
1006  LONG Exponent;
1007 
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)))
1012  {
1013  /* The result will be indefinite */
1014  Result->Sign = TRUE;
1015  Result->Exponent = FPU_MAX_EXPONENT + 1;
1016  Result->Mantissa = FPU_INDEFINITE_MANTISSA;
1017  return TRUE;
1018  }
1019 
1020  if (FPU_IS_ZERO(FirstOperand) || FPU_IS_ZERO(SecondOperand))
1021  {
1022  /* The result will be zero */
1023  Result->Sign = FirstOperand->Sign ^ SecondOperand->Sign;
1024  Result->Exponent = 0;
1025  Result->Mantissa = 0ULL;
1026  return TRUE;
1027  }
1028 
1029  if (FPU_IS_INFINITY(FirstOperand) || FPU_IS_INFINITY(SecondOperand))
1030  {
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;
1035  return TRUE;
1036  }
1037 
1038  if ((!FPU_IS_NORMALIZED(FirstOperand) || !FPU_IS_NORMALIZED(SecondOperand)))
1039  {
1040  /* Raise the denormalized exception */
1041  State->FpuStatus.De = TRUE;
1042 
1043  if (!State->FpuControl.Dm)
1044  {
1045  return FALSE;
1046  }
1047  }
1048 
1049  /* Calculate the sign */
1050  TempResult.Sign = FirstOperand->Sign ^ SecondOperand->Sign;
1051 
1052  /* Calculate the exponent */
1053  Exponent = (LONG)FirstOperand->Exponent + (LONG)SecondOperand->Exponent - FPU_REAL10_BIAS + 1;
1054 
1055  /* Calculate the mantissa */
1056  UnsignedMult128(FirstOperand->Mantissa,
1057  SecondOperand->Mantissa,
1058  &TempResult.Mantissa);
1059 
1060  if (Exponent < 0)
1061  {
1062  /* Raise the underflow exception */
1063  State->FpuStatus.Ue = TRUE;
1064 
1065  if (!State->FpuControl.Um)
1066  {
1067  return FALSE;
1068  }
1069 
1070  /* The exponent will be zero */
1071  TempResult.Exponent = 0;
1072 
1073  /* If possible, denormalize the result, otherwise make it zero */
1074  if (Exponent > -64) TempResult.Mantissa >>= (-Exponent);
1075  else TempResult.Mantissa = 0ULL;
1076  }
1077  else if (Exponent > FPU_MAX_EXPONENT)
1078  {
1079  /* Raise the overflow exception */
1080  State->FpuStatus.Oe = TRUE;
1081 
1082  if (!State->FpuControl.Om)
1083  {
1084  return FALSE;
1085  }
1086 
1087  /* Make the result infinity */
1088  TempResult.Exponent = FPU_MAX_EXPONENT + 1;
1089  TempResult.Mantissa = FPU_MANTISSA_HIGH_BIT;
1090  }
1091  else TempResult.Exponent = (USHORT)Exponent;
1092 
1093  /* Normalize the result */
1094  if (!Fast486FpuNormalize(State, &TempResult))
1095  {
1096  /* Exception occurred */
1097  return FALSE;
1098  }
1099 
1100  *Result = TempResult;
1101  return TRUE;
1102 }
1103 
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)
1109 {
1110  FAST486_FPU_DATA_REG TempResult;
1111  ULONGLONG QuotientLow, QuotientHigh, Remainder;
1112  LONG Exponent;
1113 
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)))
1118  {
1119  /* Raise the invalid operation exception */
1120  State->FpuStatus.Ie = TRUE;
1121 
1122  if (State->FpuControl.Im)
1123  {
1124  /* Return the indefinite NaN */
1125  Result->Sign = TRUE;
1126  Result->Exponent = FPU_MAX_EXPONENT + 1;
1127  Result->Mantissa = FPU_INDEFINITE_MANTISSA;
1128  return TRUE;
1129  }
1130  else
1131  {
1132  return FALSE;
1133  }
1134  }
1135 
1136  if (FPU_IS_ZERO(SecondOperand) || FPU_IS_INFINITY(FirstOperand))
1137  {
1138  /* Raise the division by zero exception */
1139  State->FpuStatus.Ze = TRUE;
1140 
1141  if (State->FpuControl.Zm)
1142  {
1143  /* Return infinity */
1144  Result->Sign = FirstOperand->Sign;
1145  Result->Exponent = FPU_MAX_EXPONENT + 1;
1146  Result->Mantissa = FPU_MANTISSA_HIGH_BIT;
1147  return TRUE;
1148  }
1149  else
1150  {
1151  return FALSE;
1152  }
1153  }
1154 
1155  /* Calculate the sign of the result */
1156  TempResult.Sign = FirstOperand->Sign ^ SecondOperand->Sign;
1157 
1158  if (FPU_IS_ZERO(FirstOperand) || FPU_IS_INFINITY(SecondOperand))
1159  {
1160  /* Return zero */
1161  Result->Sign = TempResult.Sign;
1162  Result->Mantissa = 0ULL;
1163  Result->Exponent = 0;
1164  return TRUE;
1165  }
1166 
1167  /* Calculate the exponent of the result */
1168  Exponent = (LONG)FirstOperand->Exponent - (LONG)SecondOperand->Exponent - 1;
1169 
1170  /* Divide the two mantissas */
1172  FirstOperand->Mantissa,
1173  SecondOperand->Mantissa,
1174  &QuotientLow,
1175  &QuotientHigh);
1176  UNREFERENCED_PARAMETER(Remainder); // TODO: Rounding
1177 
1178  TempResult.Mantissa = QuotientLow;
1179 
1180  if (QuotientHigh > 0ULL)
1181  {
1182  ULONG BitsToShift = 64 - CountLeadingZeros64(QuotientHigh);
1183 
1184  TempResult.Mantissa >>= BitsToShift;
1185  TempResult.Mantissa |= QuotientHigh << (64 - BitsToShift);
1186  Exponent += BitsToShift;
1187 
1188  // TODO: Rounding
1189  }
1190 
1191  if (Exponent < -FPU_REAL10_BIAS)
1192  {
1193  TempResult.Mantissa >>= -(Exponent + FPU_REAL10_BIAS);
1194  Exponent = -FPU_REAL10_BIAS;
1195 
1196  // TODO: Rounding
1197  }
1198 
1199  TempResult.Exponent = (USHORT)(Exponent + FPU_REAL10_BIAS);
1200 
1201  /* Normalize the result */
1202  if (!Fast486FpuNormalize(State, &TempResult))
1203  {
1204  /* Exception occurred */
1205  return FALSE;
1206  }
1207 
1208  *Result = TempResult;
1209  return TRUE;
1210 }
1211 
1212 /*
1213  * Calculates using the identity:
1214  * 2 ^ x - 1 = 1 + sum { 2 * (((x - 1) * ln(2)) ^ n) / n! }
1215  */
1216 static inline VOID FASTCALL
1218  PCFAST486_FPU_DATA_REG Operand,
1219  PFAST486_FPU_DATA_REG Result)
1220 {
1221  INT i;
1222  FAST486_FPU_DATA_REG TempResult = FpuOne;
1223  FAST486_FPU_DATA_REG Value;
1224  FAST486_FPU_DATA_REG SeriesElement;
1225 
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;
1230 
1231  for (i = 2; i <= INVERSE_NUMBERS_COUNT; i++)
1232  {
1233  /* Add the series element to the final sum */
1234  if (!Fast486FpuAdd(State, &TempResult, &SeriesElement, &TempResult))
1235  {
1236  /* An exception occurred */
1237  return;
1238  }
1239 
1240  /*
1241  * Calculate the next series element (partially) by multiplying
1242  * it with (x - 1) * ln(2)
1243  */
1244  if (!Fast486FpuMultiply(State, &SeriesElement, &Value, &SeriesElement))
1245  {
1246  /* An exception occurred */
1247  return;
1248  }
1249 
1250  /* And now multiply the series element by the inverse counter */
1252  &SeriesElement,
1253  &FpuInverseNumber[i - 1],
1254  &SeriesElement))
1255  {
1256  /* An exception occurred */
1257  return;
1258  }
1259  }
1260 
1261  *Result = TempResult;
1262 }
1263 
1264 static inline BOOLEAN FASTCALL
1266  PCFAST486_FPU_DATA_REG Operand,
1267  PFAST486_FPU_DATA_REG Result)
1268 {
1269  INT i;
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;
1274 
1275  if (Operand->Sign)
1276  {
1277  /* Raise the invalid operation exception */
1278  State->FpuStatus.Ie = TRUE;
1279 
1280  if (State->FpuControl.Im)
1281  {
1282  /* Return the indefinite NaN */
1283  Result->Sign = TRUE;
1284  Result->Exponent = FPU_MAX_EXPONENT + 1;
1285  Result->Mantissa = FPU_INDEFINITE_MANTISSA;
1286  return TRUE;
1287  }
1288  else
1289  {
1290  return FALSE;
1291  }
1292  }
1293 
1294  /* Get only the mantissa as a floating-pointer number between 1 and 2 */
1295  Value.Exponent = FPU_REAL10_BIAS;
1296 
1297  /* Check if it's denormalized */
1298  if (!FPU_IS_NORMALIZED(&Value))
1299  {
1300  ULONG Bits;
1301  State->FpuStatus.De = TRUE;
1302 
1303  if (!State->FpuControl.Dm)
1304  {
1305  return FALSE;
1306  }
1307 
1308  /* Normalize the number */
1309  Bits = CountLeadingZeros64(Value.Mantissa);
1310  UnbiasedExp -= Bits;
1311  Value.Mantissa <<= Bits;
1312  }
1313 
1314  TempResult.Sign = FALSE;
1315  TempResult.Exponent = FPU_REAL10_BIAS - 1;
1316  TempResult.Mantissa = 0ULL;
1317 
1318  for (i = 63; i >= 0; i--)
1319  {
1320  /* Square the value */
1321  if (!Fast486FpuMultiply(State, &Value, &Value, &Value)) return FALSE;
1322 
1323  /* Subtract two from it */
1324  if (!Fast486FpuSubtract(State, &Value, &FpuTwo, &TempValue)) return FALSE;
1325 
1326  /* Is the result positive? */
1327  if (!TempValue.Sign)
1328  {
1329  /* Yes, set the appropriate bit in the mantissa */
1330  TempResult.Mantissa |= 1ULL << i;
1331 
1332  /* Halve the value */
1333  if (!Fast486FpuMultiply(State, &Value, &FpuInverseNumber[1], &Value)) return FALSE;
1334  }
1335  }
1336 
1337  /* Normalize the result */
1338  if (!Fast486FpuNormalize(State, &TempResult)) return FALSE;
1339 
1340  /*
1341  * Add the exponent to the result
1342  * log2(x * 2^y) = log2(x) + log2(2^y) = log2(x) + y
1343  */
1344  Fast486FpuFromInteger(State, UnbiasedExp, &TempValue);
1345  if (!Fast486FpuAdd(State, &TempValue, &TempResult, &TempResult)) return FALSE;
1346 
1347  *Result = TempResult;
1348  return TRUE;
1349 }
1350 
1351 static inline BOOLEAN FASTCALL
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)
1358 {
1359  BOOLEAN Success = FALSE;
1360  INT OldRoundingMode = State->FpuControl.Rc;
1361  LONGLONG Integer;
1362  FAST486_FPU_DATA_REG Temp;
1363 
1364  if (!Fast486FpuDivide(State, FirstOperand, SecondOperand, &Temp)) return FALSE;
1365 
1366  State->FpuControl.Rc = RoundToNearest ? FPU_ROUND_NEAREST : FPU_ROUND_TRUNCATE;
1367 
1368  if (!Fast486FpuToInteger(State, &Temp, &Integer)) goto Cleanup;
1369 
1370  if (Result)
1371  {
1372  Fast486FpuFromInteger(State, Integer, &Temp);
1373  if (!Fast486FpuMultiply(State, &Temp, SecondOperand, &Temp)) goto Cleanup;
1374  if (!Fast486FpuSubtract(State, FirstOperand, &Temp, Result)) goto Cleanup;
1375  }
1376 
1377  if (Quotient) *Quotient = Integer;
1378  Success = TRUE;
1379 
1380 Cleanup:
1381  State->FpuControl.Rc = OldRoundingMode;
1382  return Success;
1383 }
1384 
1385 /*
1386  * Calculates using the identity:
1387  * sin(x) = sum { -1^n * x^(2n + 1) / (2n + 1)!, n >= 0 }
1388  */
1389 static inline BOOLEAN FASTCALL
1391  PCFAST486_FPU_DATA_REG Operand,
1392  PFAST486_FPU_DATA_REG Result)
1393 {
1394  INT i;
1395  ULONGLONG Quadrant;
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;
1401 
1403  Operand,
1404  &FpuHalfPi,
1405  FALSE,
1406  &Normalized,
1407  (PLONGLONG)&Quadrant))
1408  {
1409  return FALSE;
1410  }
1411 
1412  /* Normalize the quadrant number */
1413  Quadrant &= 3;
1414 
1415  if (!(Quadrant & 1))
1416  {
1417  /* This is a sine */
1419  TempResult = SeriesElement = Normalized;
1420  }
1421  else
1422  {
1423  /* This is a cosine */
1425  TempResult = SeriesElement = FpuOne;
1426  }
1427 
1428  /* Calculate the square of the operand */
1429  if (!Fast486FpuMultiply(State, &Normalized, &Normalized, &OperandSquared)) return FALSE;
1430 
1431  for (i = 0; i < INVERSE_NUMBERS_COUNT; i++)
1432  {
1433  if (!Fast486FpuMultiply(State, &SeriesElement, &OperandSquared, &SeriesElement))
1434  {
1435  /* An exception occurred */
1436  return FALSE;
1437  }
1438 
1440  &SeriesElement,
1441  &Inverse[i],
1442  &SeriesElement))
1443  {
1444  /* An exception occurred */
1445  return FALSE;
1446  }
1447 
1448  /* Toggle the sign of the series element */
1449  SeriesElement.Sign = !SeriesElement.Sign;
1450 
1451  if (!Fast486FpuAdd(State, &TempResult, &SeriesElement, &TempResult))
1452  {
1453  /* An exception occurred */
1454  return FALSE;
1455  }
1456  }
1457 
1458  /* Flip the sign for the third and fourth quadrant */
1459  if (Quadrant >= 2) TempResult.Sign = !TempResult.Sign;
1460 
1461  *Result = TempResult;
1462  return TRUE;
1463 }
1464 
1465 /*
1466  * Calculates using the identity:
1467  * cos(x) = sum { -1^n * x^(2n) / (2n)!, n >= 0 }
1468  */
1469 static inline BOOLEAN FASTCALL
1471  PCFAST486_FPU_DATA_REG Operand,
1472  PFAST486_FPU_DATA_REG Result)
1473 {
1474  FAST486_FPU_DATA_REG Value = *Operand;
1475 
1476  /* Add pi / 2 */
1477  if (!Fast486FpuAdd(State, &Value, &FpuHalfPi, &Value)) return FALSE;
1478 
1479  /* Calculate the sine */
1481 }
1482 
1483 static inline VOID FASTCALL
1485  INT Operation,
1486  PFAST486_FPU_DATA_REG Operand,
1487  BOOLEAN TopDestination)
1488 {
1489  PFAST486_FPU_DATA_REG DestOperand = TopDestination ? &FPU_ST(0) : Operand;
1490 
1491  ASSERT(!(Operation & ~7));
1492 
1493  /* Check the operation */
1494  switch (Operation)
1495  {
1496  /* FADD */
1497  case 0:
1498  {
1499  Fast486FpuAdd(State, &FPU_ST(0), Operand, DestOperand);
1500  break;
1501  }
1502 
1503  /* FMUL */
1504  case 1:
1505  {
1506  Fast486FpuMultiply(State, &FPU_ST(0), Operand, DestOperand);
1507  break;
1508  }
1509 
1510  /* FCOM */
1511  case 2:
1512  /* FCOMP */
1513  case 3:
1514  {
1515  Fast486FpuCompare(State, &FPU_ST(0), Operand);
1516  if (Operation == 3) Fast486FpuPop(State);
1517 
1518  break;
1519  }
1520 
1521  /* FSUB */
1522  case 4:
1523  {
1524  Fast486FpuSubtract(State, &FPU_ST(0), Operand, DestOperand);
1525  break;
1526  }
1527 
1528  /* FSUBR */
1529  case 5:
1530  {
1531  Fast486FpuSubtract(State, Operand, &FPU_ST(0), DestOperand);
1532  break;
1533  }
1534 
1535  /* FDIV */
1536  case 6:
1537  {
1538  Fast486FpuDivide(State, &FPU_ST(0), Operand, DestOperand);
1539  break;
1540  }
1541 
1542  /* FDIVR */
1543  case 7:
1544  {
1545  Fast486FpuDivide(State, Operand, &FPU_ST(0), DestOperand);
1546  break;
1547  }
1548  }
1549 }
1550 
1551 /*
1552  * Calculates using:
1553  * x[0] = s
1554  * x[n + 1] = (x[n] + s / x[n]) / 2
1555  */
1556 static inline BOOLEAN FASTCALL
1558  PCFAST486_FPU_DATA_REG Operand,
1559  PFAST486_FPU_DATA_REG Result)
1560 {
1561  FAST486_FPU_DATA_REG Value = *Operand;
1562  FAST486_FPU_DATA_REG PrevValue = FpuZero;
1563 
1564  if (Operand->Sign)
1565  {
1566  /* Raise the invalid operation exception */
1567  State->FpuStatus.Ie = TRUE;
1568 
1569  if (State->FpuControl.Im)
1570  {
1571  /* Return the indefinite NaN */
1572  Result->Sign = TRUE;
1573  Result->Exponent = FPU_MAX_EXPONENT + 1;
1574  Result->Mantissa = FPU_INDEFINITE_MANTISSA;
1575  return TRUE;
1576  }
1577  else
1578  {
1579  return FALSE;
1580  }
1581  }
1582 
1583  /* Loop until it converges */
1584  while (Value.Sign != PrevValue.Sign
1585  || Value.Exponent != PrevValue.Exponent
1586  || Value.Mantissa != PrevValue.Mantissa)
1587  {
1588  FAST486_FPU_DATA_REG Temp;
1589 
1590  /* Save the current value */
1591  PrevValue = Value;
1592 
1593  /* Divide the operand by the current value */
1594  if (!Fast486FpuDivide(State, Operand, &Value, &Temp)) return FALSE;
1595 
1596  /* Add the result of that division to the current value */
1597  if (!Fast486FpuAdd(State, &Value, &Temp, &Value)) return FALSE;
1598 
1599  /* Halve the current value */
1600  if (!Fast486FpuMultiply(State, &Value, &FpuInverseNumber[1], &Value)) return FALSE;
1601  }
1602 
1603  *Result = Value;
1604  return TRUE;
1605 }
1606 
1607 /*
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 }
1611  */
1612 static inline BOOLEAN FASTCALL
1614  PCFAST486_FPU_DATA_REG Numerator,
1615  PCFAST486_FPU_DATA_REG Denominator,
1616  PFAST486_FPU_DATA_REG Result)
1617 {
1618  INT i;
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;
1626 
1627  TempNumerator.Sign = FALSE;
1628  TempDenominator.Sign = FALSE;
1629 
1630  /* Compare the numerator to the denominator */
1631  if (!Fast486FpuSubtract(State, &TempNumerator, &TempDenominator, &TempResult))
1632  {
1633  return FALSE;
1634  }
1635 
1636  if ((Inverted = !TempResult.Sign))
1637  {
1638  if (!Fast486FpuDivide(State, &TempDenominator, &TempNumerator, &Value))
1639  {
1640  return FALSE;
1641  }
1642  }
1643  else
1644  {
1645  if (!Fast486FpuDivide(State, &TempNumerator, &TempDenominator, &Value))
1646  {
1647  return FALSE;
1648  }
1649  }
1650 
1651  /* Apparently, atan2(0, 0) = +/- 0 or +/- pi for some reason... */
1653 
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;
1658 
1659  TempResult = FpuOne;
1660 
1661  for (i = 0; i < INVERSE_NUMBERS_COUNT; i++)
1662  {
1663  if (!Fast486FpuMultiply(State, &SeriesElement, &Value, &SeriesElement))
1664  {
1665  /* An exception occurred */
1666  return FALSE;
1667  }
1668 
1669  if (!Fast486FpuMultiply(State, &SeriesElement, &ValDivValSqP1, &SeriesElement))
1670  {
1671  /* An exception occurred */
1672  return FALSE;
1673  }
1674 
1676  &SeriesElement,
1678  &SeriesElement))
1679  {
1680  /* An exception occurred */
1681  return FALSE;
1682  }
1683 
1684  if (!Fast486FpuAdd(State, &TempResult, &SeriesElement, &TempResult))
1685  {
1686  /* An exception occurred */
1687  return FALSE;
1688  }
1689  }
1690 
1691  if (!Fast486FpuMultiply(State, &TempResult, &ValDivValSqP1, &TempResult))
1692  {
1693  /* An exception occurred */
1694  return FALSE;
1695  }
1696 
1697  if (Inverted)
1698  {
1699  /* Since y/x is positive, arctan(y/x) = pi/2 - arctan(x/y) */
1700  if (!Fast486FpuSubtract(State, &FpuHalfPi, &TempResult, &TempResult)) return FALSE;
1701  }
1702 
1703  /* Adjust the sign */
1704  if (!(!Numerator->Sign == !Denominator->Sign)) TempResult.Sign = !TempResult.Sign;
1705 
1706  if (Denominator->Sign)
1707  {
1708  if (Numerator->Sign)
1709  {
1710  /* Subtract PI */
1711  if (!Fast486FpuSubtract(State, &TempResult, &FpuPi, &TempResult)) return FALSE;
1712  }
1713  else
1714  {
1715  /* Add PI */
1716  if (!Fast486FpuAdd(State, &TempResult, &FpuPi, &TempResult)) return FALSE;
1717  }
1718  }
1719 
1720  *Result = TempResult;
1721  return TRUE;
1722 }
1723 
1724 static inline BOOLEAN FASTCALL
1726  INT Segment,
1727  ULONG Address,
1728  BOOLEAN Size)
1729 {
1730  UCHAR Buffer[28];
1731 
1732  if (!Fast486ReadMemory(State, Segment, Address, FALSE, Buffer, (Size + 1) * 14))
1733  {
1734  /* Exception occurred */
1735  return FALSE;
1736  }
1737 
1738  /* Check if this is a 32-bit save or a 16-bit save */
1739  if (Size)
1740  {
1741  PULONG Data = (PULONG)Buffer;
1742 
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];
1750  }
1751  else
1752  {
1754 
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];
1762  }
1763 
1764  return TRUE;
1765 }
1766 
1767 static inline BOOLEAN FASTCALL
1769  INT Segment,
1770  ULONG Address,
1771  BOOLEAN Size)
1772 {
1773  UCHAR Buffer[28];
1774 
1775  /* Check if this is a 32-bit save or a 16-bit save */
1776  if (Size)
1777  {
1778  PULONG Data = (PULONG)Buffer;
1779 
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;
1787  }
1788  else
1789  {
1791 
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;
1799  }
1800 
1801  return Fast486WriteMemory(State, Segment, Address, Buffer, (Size + 1) * 14);
1802 }
1803 
1804 #endif
1805 
1806 /* PUBLIC FUNCTIONS ***********************************************************/
1807 
1808 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8)
1809 {
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;
1815 #endif
1816 
1817  TOGGLE_ADSIZE(AddressSize);
1818 
1819  /* Get the operands */
1820  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1821  {
1822  /* Exception occurred */
1823  return;
1824  }
1825 
1826  FPU_CHECK();
1827 
1828 #ifndef FAST486_NO_FPU
1829 
1830  Fast486FpuExceptionCheck(State);
1832 
1833  if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
1834  {
1835  /* Raise the invalid operation exception */
1836  State->FpuStatus.Ie = TRUE;
1837 
1838  if (State->FpuControl.Im)
1839  {
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;
1844 
1846  }
1847 
1848  return;
1849  }
1850 
1851  if (ModRegRm.Memory)
1852  {
1853  /* Load the source operand from memory */
1854  ULONG Value;
1855 
1856  if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
1857  {
1858  /* Exception occurred */
1859  return;
1860  }
1861 
1862  Fast486FpuFromSingleReal(State, Value, &MemoryData);
1863  Operand = &MemoryData;
1864 
1866  }
1867  else
1868  {
1869  if (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
1870  {
1871  /* Raise the invalid operation exception */
1872  State->FpuStatus.Ie = TRUE;
1873 
1874  if (State->FpuControl.Im)
1875  {
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;
1880 
1882  }
1883 
1884  return;
1885  }
1886 
1887  /* Load the source operand from an FPU register */
1888  Operand = &FPU_ST(ModRegRm.SecondRegister);
1889  }
1890 
1891  /* Perform the requested operation */
1892  Fast486FpuArithmeticOperation(State, ModRegRm.Register, Operand, TRUE);
1893 
1894 #endif
1895 }
1896 
1897 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9)
1898 {
1899  FAST486_MOD_REG_RM ModRegRm;
1900  BOOLEAN OperandSize, AddressSize;
1901 
1902  OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1903  TOGGLE_OPSIZE(OperandSize);
1904  TOGGLE_ADSIZE(AddressSize);
1905 
1906  /* Get the operands */
1907  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1908  {
1909  /* Exception occurred */
1910  return;
1911  }
1912 
1913  FPU_CHECK();
1914 
1915 #ifndef FAST486_NO_FPU
1916 
1917  if (ModRegRm.Memory)
1918  {
1919  switch (ModRegRm.Register)
1920  {
1921  /* FLD */
1922  case 0:
1923  {
1924  ULONG Value;
1925  FAST486_FPU_DATA_REG MemoryData;
1926 
1927  Fast486FpuExceptionCheck(State);
1930 
1931  if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
1932  {
1933  /* Exception occurred */
1934  return;
1935  }
1936 
1937  Fast486FpuFromSingleReal(State, Value, &MemoryData);
1938  Fast486FpuPush(State, &MemoryData);
1939 
1940  break;
1941  }
1942 
1943  /* FST */
1944  case 2:
1945  /* FSTP */
1946  case 3:
1947  {
1949 
1950  Fast486FpuExceptionCheck(State);
1953 
1954  if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
1955  {
1956  /* Raise the invalid operation exception */
1957  State->FpuStatus.Ie = TRUE;
1958 
1959  if (!State->FpuControl.Im)
1960  {
1961  return;
1962  }
1963  }
1964  else if (!Fast486FpuToSingleReal(State, &FPU_ST(0), &Value))
1965  {
1966  /* Exception occurred */
1967  return;
1968  }
1969 
1970  if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value))
1971  {
1972  /* Exception occurred */
1973  return;
1974  }
1975 
1976  if (ModRegRm.Register == 3) Fast486FpuPop(State);
1977  break;
1978  }
1979 
1980  /* FLDENV */
1981  case 4:
1982  {
1984  (State->PrefixFlags & FAST486_PREFIX_SEG)
1985  ? State->SegmentOverride : FAST486_REG_DS,
1986  ModRegRm.MemoryAddress,
1987  OperandSize);
1988  break;
1989  }
1990 
1991  /* FLDCW */
1992  case 5:
1993  {
1994  Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &State->FpuControl.Value);
1995  break;
1996  }
1997 
1998  /* FSTENV */
1999  case 6:
2000  {
2002  (State->PrefixFlags & FAST486_PREFIX_SEG)
2003  ? State->SegmentOverride : FAST486_REG_DS,
2004  ModRegRm.MemoryAddress,
2005  OperandSize);
2006  break;
2007  }
2008 
2009  /* FSTCW */
2010  case 7:
2011  {
2012  Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, State->FpuControl.Value);
2013  break;
2014  }
2015 
2016  /* Invalid */
2017  default:
2018  {
2019  Fast486Exception(State, FAST486_EXCEPTION_UD);
2020  return;
2021  }
2022  }
2023  }
2024  else
2025  {
2026  switch ((ModRegRm.Register << 3) | ModRegRm.SecondRegister)
2027  {
2028  /* FLD */
2029  case 0x00:
2030  case 0x01:
2031  case 0x02:
2032  case 0x03:
2033  case 0x04:
2034  case 0x05:
2035  case 0x06:
2036  case 0x07:
2037  {
2038  Fast486FpuExceptionCheck(State);
2040 
2041  if (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
2042  {
2043  /* Raise the invalid operation exception */
2044  State->FpuStatus.Ie = TRUE;
2045 
2046  if (!State->FpuControl.Im)
2047  {
2048  return;
2049  }
2050  }
2051 
2052  Fast486FpuPush(State, &FPU_ST(ModRegRm.SecondRegister));
2053  break;
2054  }
2055 
2056  /* FXCH */
2057  case 0x08:
2058  case 0x09:
2059  case 0x0A:
2060  case 0x0B:
2061  case 0x0C:
2062  case 0x0D:
2063  case 0x0E:
2064  case 0x0F:
2065  {
2066  FAST486_FPU_DATA_REG Temp;
2067 
2068  Fast486FpuExceptionCheck(State);
2070 
2071  if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2072  || FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
2073  {
2074  State->FpuStatus.Ie = TRUE;
2075  break;
2076  }
2077 
2078  /* Exchange */
2079  Temp = FPU_ST(0);
2080  FPU_ST(0) = FPU_ST(ModRegRm.SecondRegister);
2081  FPU_ST(ModRegRm.SecondRegister) = Temp;
2082 
2083  FPU_UPDATE_TAG(0);
2084  FPU_UPDATE_TAG(ModRegRm.SecondRegister);
2085 
2086  break;
2087  }
2088 
2089  /* FNOP */
2090  case 0x10:
2091  {
2092  /* Do nothing */
2093  break;
2094  }
2095 
2096  /* FSTP */
2097  case 0x18:
2098  case 0x19:
2099  case 0x1A:
2100  case 0x1B:
2101  case 0x1C:
2102  case 0x1D:
2103  case 0x1E:
2104  case 0x1F:
2105  {
2106  Fast486FpuExceptionCheck(State);
2108 
2109  FPU_ST(ModRegRm.SecondRegister) = FPU_ST(0);
2110  FPU_UPDATE_TAG(ModRegRm.SecondRegister);
2111 
2112  Fast486FpuPop(State);
2113  break;
2114  }
2115 
2116  /* FCHS */
2117  case 0x20:
2118  {
2119  Fast486FpuExceptionCheck(State);
2121 
2122  if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2123  {
2124  State->FpuStatus.Ie = TRUE;
2125  break;
2126  }
2127 
2128  /* Invert the sign */
2129  FPU_ST(0).Sign = !FPU_ST(0).Sign;
2130 
2131  break;
2132  }
2133 
2134  /* FABS */
2135  case 0x21:
2136  {
2137  Fast486FpuExceptionCheck(State);
2139 
2140  if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2141  {
2142  State->FpuStatus.Ie = TRUE;
2143  break;
2144  }
2145 
2146  /* Set the sign to positive */
2147  FPU_ST(0).Sign = FALSE;
2148 
2149  break;
2150  }
2151 
2152  /* FTST */
2153  case 0x24:
2154  {
2155  Fast486FpuExceptionCheck(State);
2157 
2159  break;
2160  }
2161 
2162  /* FXAM */
2163  case 0x25:
2164  {
2165  Fast486FpuExceptionCheck(State);
2167 
2168  /* The sign bit goes in C1, even if the register's empty */
2169  State->FpuStatus.Code1 = FPU_ST(0).Sign;
2170 
2171  if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2172  {
2173  State->FpuStatus.Code0 = 1;
2174  State->FpuStatus.Code2 = 0;
2175  State->FpuStatus.Code3 = 1;
2176  }
2177  else if (FPU_GET_TAG(0) == FPU_TAG_SPECIAL)
2178  {
2179  if (FPU_IS_INFINITY(&FPU_ST(0)))
2180  {
2181  State->FpuStatus.Code0 = 1;
2182  State->FpuStatus.Code2 = 1;
2183  State->FpuStatus.Code3 = 0;
2184  }
2185  else
2186  {
2187  State->FpuStatus.Code0 = 1;
2188  State->FpuStatus.Code2 = 0;
2189  State->FpuStatus.Code3 = 0;
2190  }
2191  }
2192  else if (FPU_GET_TAG(0) == FPU_TAG_ZERO)
2193  {
2194  State->FpuStatus.Code0 = 0;
2195  State->FpuStatus.Code2 = 0;
2196  State->FpuStatus.Code3 = 1;
2197  }
2198  else
2199  {
2200  if (FPU_IS_NORMALIZED(&FPU_ST(0)))
2201  {
2202  State->FpuStatus.Code0 = 0;
2203  State->FpuStatus.Code2 = 1;
2204  State->FpuStatus.Code3 = 0;
2205  }
2206  else
2207  {
2208  State->FpuStatus.Code0 = 0;
2209  State->FpuStatus.Code2 = 1;
2210  State->FpuStatus.Code3 = 1;
2211  }
2212  }
2213 
2214  break;
2215  }
2216 
2217  /* FLD1 */
2218  case 0x28:
2219  /* FLDL2T */
2220  case 0x29:
2221  /* FLDL2E */
2222  case 0x2A:
2223  /* FLDPI */
2224  case 0x2B:
2225  /* FLDLG2 */
2226  case 0x2C:
2227  /* FLDLN2 */
2228  case 0x2D:
2229  /* FLDZ */
2230  case 0x2E:
2231  {
2232  PCFAST486_FPU_DATA_REG Constants[] =
2233  {
2234  &FpuOne,
2235  &FpuL2Ten,
2236  &FpuL2E,
2237  &FpuPi,
2238  &FpuLgTwo,
2239  &FpuLnTwo,
2240  &FpuZero
2241  };
2242 
2243  Fast486FpuExceptionCheck(State);
2245 
2246  Fast486FpuPush(State, Constants[ModRegRm.SecondRegister]);
2247  break;
2248  }
2249 
2250  /* F2XM1 */
2251  case 0x30:
2252  {
2253  Fast486FpuExceptionCheck(State);
2255 
2256  if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2257  {
2258  State->FpuStatus.Ie = TRUE;
2259  break;
2260  }
2261 
2262  if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2263  {
2264  State->FpuStatus.De = TRUE;
2265 
2266  if (!State->FpuControl.Dm)
2267  {
2268  break;
2269  }
2270  }
2271 
2273  FPU_UPDATE_TAG(0);
2274 
2275  break;
2276  }
2277 
2278  /* FYL2X */
2279  case 0x31:
2280  {
2281  FAST486_FPU_DATA_REG Logarithm;
2282 
2283  Fast486FpuExceptionCheck(State);
2285 
2287  {
2288  State->FpuStatus.Ie = TRUE;
2289  break;
2290  }
2291 
2292  if (!Fast486FpuCalculateLogBase2(State, &FPU_ST(0), &Logarithm))
2293  {
2294  /* Exception occurred */
2295  break;
2296  }
2297 
2298  if (!Fast486FpuMultiply(State, &Logarithm, &FPU_ST(1), &FPU_ST(1)))
2299  {
2300  /* Exception occurred */
2301  break;
2302  }
2303 
2304  /* Pop the stack so that the result ends up in ST0 */
2305  Fast486FpuPop(State);
2306  FPU_UPDATE_TAG(0);
2307 
2308  break;
2309  }
2310 
2311  /* FPTAN */
2312  case 0x32:
2313  {
2314  FAST486_FPU_DATA_REG Sine;
2315  FAST486_FPU_DATA_REG Cosine;
2316  ULONGLONG Quadrant;
2317 
2318  Fast486FpuExceptionCheck(State);
2320 
2321  /* Compute the sine */
2322  if (!Fast486FpuCalculateSine(State, &FPU_ST(0), &Sine)) break;
2323 
2324  /* Normalize the angle */
2326  &FPU_ST(0),
2327  &FpuHalfPi,
2328  FALSE,
2329  NULL,
2330  (PLONGLONG)&Quadrant))
2331  {
2332  break;
2333  }
2334 
2335  /* Normalize the quadrant number */
2336  Quadrant &= 3;
2337 
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;
2342 
2343  /* Adjust the sign of the cosine */
2344  if (Quadrant == 1 || Quadrant == 2) Cosine.Sign = TRUE;
2345 
2346  /* Divide the sine by the cosine to get the tangent */
2347  if (!Fast486FpuDivide(State, &Sine, &Cosine, &FPU_ST(0))) break;
2348  FPU_UPDATE_TAG(0);
2349 
2350  /* Push 1.00 */
2351  Fast486FpuPush(State, &FpuOne);
2352  break;
2353  }
2354 
2355  /* FPATAN */
2356  case 0x33:
2357  {
2358  Fast486FpuExceptionCheck(State);
2360 
2362  &FPU_ST(1),
2363  &FPU_ST(0),
2364  &FPU_ST(1)))
2365  {
2366  break;
2367  }
2368 
2369  FPU_UPDATE_TAG(1);
2370 
2371  Fast486FpuPop(State);
2372  break;
2373  }
2374 
2375  /* FXTRACT */
2376  case 0x34:
2377  {
2378  FAST486_FPU_DATA_REG Value = FPU_ST(0);
2379 
2380  Fast486FpuExceptionCheck(State);
2382 
2384  {
2385  State->FpuStatus.Ie = TRUE;
2386  if (FPU_GET_TAG(0) == FPU_TAG_EMPTY) State->FpuStatus.Sf = TRUE;
2387  break;
2388  }
2389 
2390  if (FPU_IS_ZERO(&Value))
2391  {
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;
2396  }
2397  else if (FPU_IS_INFINITY(&Value))
2398  {
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;
2403  }
2404  else
2405  {
2406  /* Store the unbiased exponent in ST0 */
2408  (LONGLONG)Value.Exponent - (LONGLONG)FPU_REAL10_BIAS,
2409  &FPU_ST(0));
2410  }
2411 
2412  /* Now push the mantissa as a real number, with the original sign */
2413  Value.Exponent = FPU_REAL10_BIAS;
2414  Fast486FpuPush(State, &Value);
2415 
2416  break;
2417  }
2418 
2419  /* FPREM1 */
2420  case 0x35:
2421  /* FPREM */
2422  case 0x38:
2423  {
2424  LONGLONG Quotient;
2425 
2426  Fast486FpuExceptionCheck(State);
2428 
2430  {
2431  State->FpuStatus.Ie = TRUE;
2432  break;
2433  }
2434 
2436  &FPU_ST(0),
2437  &FPU_ST(1),
2438  ModRegRm.Register == 6, /* TRUE if it's FPREM1 */
2439  &FPU_ST(0),
2440  &Quotient))
2441  {
2442  FPU_UPDATE_TAG(0);
2443 
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;
2448  }
2449 
2450  break;
2451  }
2452 
2453  /* FDECSTP */
2454  case 0x36:
2455  {
2456  State->FpuStatus.Top--;
2457  break;
2458  }
2459 
2460  /* FINCSTP */
2461  case 0x37:
2462  {
2463  State->FpuStatus.Top++;
2464  break;
2465  }
2466 
2467  /* FYL2XP1 */
2468  case 0x39:
2469  {
2470  FAST486_FPU_DATA_REG Value, Logarithm;
2471 
2472  Fast486FpuExceptionCheck(State);
2474 
2476  {
2477  State->FpuStatus.Ie = TRUE;
2478  break;
2479  }
2480 
2481  if (!Fast486FpuAdd(State, &FPU_ST(0), &FpuOne, &Value))
2482  {
2483  /* Exception occurred */
2484  break;
2485  }
2486 
2487  if (!Fast486FpuCalculateLogBase2(State, &Value, &Logarithm))
2488  {
2489  /* Exception occurred */
2490  break;
2491  }
2492 
2493  if (!Fast486FpuMultiply(State, &Logarithm, &FPU_ST(1), &FPU_ST(1)))
2494  {
2495  /* Exception occurred */
2496  break;
2497  }
2498 
2499  /* Pop the stack so that the result ends up in ST0 */
2500  Fast486FpuPop(State);
2501  FPU_UPDATE_TAG(0);
2502 
2503  break;
2504  }
2505 
2506  /* FSQRT */
2507  case 0x3A:
2508  {
2509  Fast486FpuExceptionCheck(State);
2511 
2513  FPU_UPDATE_TAG(0);
2514 
2515  break;
2516  }
2517 
2518  /* FSINCOS */
2519  case 0x3B:
2520  {
2521  FAST486_FPU_DATA_REG Number = FPU_ST(0);
2522 
2523  Fast486FpuExceptionCheck(State);
2525 
2526  if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2527  {
2528  State->FpuStatus.Ie = TRUE;
2529  break;
2530  }
2531 
2532  if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2533  {
2534  State->FpuStatus.De = TRUE;
2535 
2536  if (!State->FpuControl.Dm)
2537  {
2538  break;
2539  }
2540  }
2541 
2542  /* Replace FP0 with the sine */
2543  if (!Fast486FpuCalculateSine(State, &Number, &FPU_ST(0))) break;
2544  FPU_UPDATE_TAG(0);
2545 
2546  /* Push the cosine */
2547  if (!Fast486FpuCalculateCosine(State, &Number, &Number)) break;
2548  Fast486FpuPush(State, &Number);
2549 
2550  break;
2551  }
2552 
2553  /* FRNDINT */
2554  case 0x3C:
2555  {
2556  LONGLONG Result = 0LL;
2557 
2558  Fast486FpuExceptionCheck(State);
2560 
2561  if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2562  {
2563  State->FpuStatus.Ie = TRUE;
2564  break;
2565  }
2566 
2567  if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2568  {
2569  State->FpuStatus.De = TRUE;
2570 
2571  if (!State->FpuControl.Dm)
2572  {
2573  break;
2574  }
2575  }
2576 
2577  /* Do nothing if it's too big to not be an integer */
2578  if (FPU_ST(0).Exponent >= FPU_REAL10_BIAS + 63) break;
2579 
2580  /* Perform the rounding */
2583 
2584  State->FpuStatus.Pe = TRUE;
2585  break;
2586  }
2587 
2588  /* FSCALE */
2589  case 0x3D:
2590  {
2591  LONGLONG Scale;
2592  LONGLONG UnbiasedExp = (LONGLONG)((SHORT)FPU_ST(0).Exponent) - FPU_REAL10_BIAS;
2593  INT OldRoundingMode = State->FpuControl.Rc;
2594 
2595  Fast486FpuExceptionCheck(State);
2597 
2599  {
2600  State->FpuStatus.Ie = TRUE;
2601  break;
2602  }
2603 
2604  if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2605  {
2606  State->FpuStatus.De = TRUE;
2607 
2608  if (!State->FpuControl.Dm)
2609  {
2610  break;
2611  }
2612  }
2613 
2614  State->FpuControl.Rc = FPU_ROUND_TRUNCATE;
2615 
2616  if (!Fast486FpuToInteger(State, &FPU_ST(1), &Scale))
2617  {
2618  /* Exception occurred */
2619  State->FpuControl.Rc = OldRoundingMode;
2620  break;
2621  }
2622 
2623  State->FpuControl.Rc = OldRoundingMode;
2624 
2625  /* Adjust the unbiased exponent */
2626  UnbiasedExp += Scale;
2627 
2628  /* Check for underflow */
2629  if (UnbiasedExp < -1023)
2630  {
2631  /* Raise the underflow exception */
2632  State->FpuStatus.Ue = TRUE;
2633 
2634  if (State->FpuControl.Um)
2635  {
2636  /* Make the result zero */
2637  FPU_ST(0) = FpuZero;
2638  FPU_UPDATE_TAG(0);
2639  }
2640 
2641  break;
2642  }
2643 
2644  /* Check for overflow */
2645  if (UnbiasedExp > 1023)
2646  {
2647  /* Raise the overflow exception */
2648  State->FpuStatus.Oe = TRUE;
2649 
2650  if (State->FpuControl.Om)
2651  {
2652  /* Make the result infinity */
2653  FPU_ST(0).Mantissa = FPU_MANTISSA_HIGH_BIT;
2654  FPU_ST(0).Exponent = FPU_MAX_EXPONENT + 1;
2655  FPU_UPDATE_TAG(0);
2656  }
2657 
2658  break;
2659  }
2660 
2661  FPU_ST(0).Exponent = (USHORT)(UnbiasedExp + FPU_REAL10_BIAS);
2662  FPU_UPDATE_TAG(0);
2663 
2664  break;
2665  }
2666 
2667  /* FSIN */
2668  case 0x3E:
2669  {
2670  Fast486FpuExceptionCheck(State);
2672 
2673  if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2674  {
2675  State->FpuStatus.Ie = TRUE;
2676  break;
2677  }
2678 
2679  if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2680  {
2681  State->FpuStatus.De = TRUE;
2682 
2683  if (!State->FpuControl.Dm)
2684  {
2685  break;
2686  }
2687  }
2688 
2690  FPU_UPDATE_TAG(0);
2691 
2692  break;
2693  }
2694 
2695  /* FCOS */
2696  case 0x3F:
2697  {
2698  Fast486FpuExceptionCheck(State);
2700 
2701  if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2702  {
2703  State->FpuStatus.Ie = TRUE;
2704  break;
2705  }
2706 
2707  if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2708  {
2709  State->FpuStatus.De = TRUE;
2710 
2711  if (!State->FpuControl.Dm)
2712  {
2713  break;
2714  }
2715  }
2716 
2718  FPU_UPDATE_TAG(0);
2719 
2720  break;
2721  }
2722 
2723  /* Invalid */
2724  default:
2725  {
2726  Fast486Exception(State, FAST486_EXCEPTION_UD);
2727  return;
2728  }
2729  }
2730  }
2731 
2732 #endif
2733 }
2734 
2735 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA)
2736 {
2737  FAST486_MOD_REG_RM ModRegRm;
2738  BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
2739 #ifndef FAST486_NO_FPU
2740  LONG Value;
2741  FAST486_FPU_DATA_REG MemoryData;
2742 #endif
2743 
2744  TOGGLE_ADSIZE(AddressSize);
2745 
2746  /* Get the operands */
2747  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
2748  {
2749  /* Exception occurred */
2750  return;
2751  }
2752 
2753  FPU_CHECK();
2754 
2755 #ifndef FAST486_NO_FPU
2756 
2757  Fast486FpuExceptionCheck(State);
2759 
2760  if (!ModRegRm.Memory)
2761  {
2762  /* The only valid opcode in this case is FUCOMPP (0xDA 0xE9) */
2763  if ((ModRegRm.Register != 5) && (ModRegRm.SecondRegister != 1))
2764  {
2765  Fast486Exception(State, FAST486_EXCEPTION_UD);
2766  return;
2767  }
2768 
2769  if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(1) == FPU_TAG_EMPTY))
2770  {
2771  /* Raise the invalid operation exception*/
2772  State->FpuStatus.Ie = TRUE;
2773  return;
2774  }
2775 
2776  /* Compare */
2777  Fast486FpuCompare(State, &FPU_ST(0), &FPU_ST(1));
2778 
2779  /* Pop twice */
2780  Fast486FpuPop(State);
2781  Fast486FpuPop(State);
2782 
2783  return;
2784  }
2785 
2787 
2788  /* Load the source operand from memory */
2789  if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, (PULONG)&Value))
2790  {
2791  /* Exception occurred */
2792  return;
2793  }
2794 
2795  if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2796  {
2797  /* Raise the invalid operation exception */
2798  State->FpuStatus.Ie = TRUE;
2799 
2800  if (State->FpuControl.Im)
2801  {
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;
2806 
2808  }
2809 
2810  return;
2811  }
2812 
2813  Fast486FpuFromInteger(State, (LONGLONG)Value, &MemoryData);
2814 
2815  /* Perform the requested operation */
2816  Fast486FpuArithmeticOperation(State, ModRegRm.Register, &MemoryData, TRUE);
2817 
2818 #endif
2819 }
2820 
2821 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB)
2822 {
2823  FAST486_MOD_REG_RM ModRegRm;
2824  BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
2825 
2826  TOGGLE_ADSIZE(AddressSize);
2827 
2828  /* Get the operands */
2829  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
2830  {
2831  /* Exception occurred */
2832  return;
2833  }
2834 
2835  FPU_CHECK();
2836 
2837 #ifndef FAST486_NO_FPU
2838 
2839  if (ModRegRm.Memory)
2840  {
2841  Fast486FpuExceptionCheck(State);
2844 
2845  switch (ModRegRm.Register)
2846  {
2847  /* FILD */
2848  case 0:
2849  {
2850  LONG Value;
2851  FAST486_FPU_DATA_REG Temp;
2852 
2853  if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, (PULONG)&Value))
2854  {
2855  /* Exception occurred */
2856  return;
2857  }
2858 
2860  Fast486FpuPush(State, &Temp);
2861 
2862  break;
2863  }
2864 
2865  /* FIST */
2866  case 2:
2867  /* FISTP */
2868  case 3:
2869  {
2870  LONGLONG Temp = 0;
2871 
2872  if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL))
2873  {
2874  /* Raise the invalid operation exception */
2875  State->FpuStatus.Ie = TRUE;
2876 
2877  if (!State->FpuControl.Im)
2878  {
2879  return;
2880  }
2881  }
2882 
2883  if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp))
2884  {
2885  /* Exception occurred */
2886  return;
2887  }
2888 
2889  /* Check if it can fit in a signed 32-bit integer */
2890  if ((LONGLONG)((LONG)Temp) != Temp)
2891  {
2892  State->FpuStatus.Ie = TRUE;
2893 
2894  if (State->FpuControl.Im)
2895  {
2896  Temp = 0x80000000LL;
2897  }
2898  else
2899  {
2900  return;
2901  }
2902  }
2903 
2904  if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, (ULONG)((LONG)Temp)))
2905  {
2906  /* Exception occurred */
2907  return;
2908  }
2909 
2910  if (ModRegRm.Register == 3)
2911  {
2912  /* Pop the FPU stack too */
2913  Fast486FpuPop(State);
2914  }
2915 
2916  break;
2917  }
2918 
2919  /* FLD */
2920  case 5:
2921  {
2922  FAST486_FPU_DATA_REG Value;
2923  UCHAR Buffer[10];
2924 
2925  if (!Fast486ReadMemory(State,
2926  (State->PrefixFlags & FAST486_PREFIX_SEG)
2927  ? State->SegmentOverride : FAST486_REG_DS,
2928  ModRegRm.MemoryAddress,
2929  FALSE,
2930  Buffer,
2931  sizeof(Buffer)))
2932  {
2933  /* Exception occurred */
2934  return;
2935  }
2936 
2937  Value.Mantissa = *((PULONGLONG)Buffer);
2938  Value.Exponent = *((PUSHORT)&Buffer[8]) & (FPU_MAX_EXPONENT + 1);
2939  Value.Sign = *((PUCHAR)&Buffer[9]) >> 7;
2940 
2941  Fast486FpuPush(State, &Value);
2942  break;
2943  }
2944 
2945  /* FSTP */
2946  case 7:
2947  {
2948  UCHAR Buffer[10];
2949 
2950  if (FPU_GET_TAG(0) != FPU_TAG_EMPTY)
2951  {
2952  *((PULONGLONG)Buffer) = FPU_ST(0).Mantissa;
2953  *((PUSHORT)&Buffer[sizeof(ULONGLONG)]) = FPU_ST(0).Exponent
2954  | (FPU_ST(0).Sign ? 0x8000 : 0);
2955  }
2956  else
2957  {
2958  /* Raise the invalid operation exception */
2959  State->FpuStatus.Ie = TRUE;
2960 
2961  if (State->FpuControl.Im)
2962  {
2964  *((PUSHORT)&Buffer[sizeof(ULONGLONG)]) = 0x8000 | (FPU_MAX_EXPONENT + 1);
2965  }
2966  else
2967  {
2968  return;
2969  }
2970  }
2971 
2973  (State->PrefixFlags & FAST486_PREFIX_SEG)
2974  ? State->SegmentOverride : FAST486_REG_DS,
2975  ModRegRm.MemoryAddress,
2976  Buffer,
2977  sizeof(Buffer)))
2978  {
2979  /* Exception occurred */
2980  return;
2981  }
2982 
2983  Fast486FpuPop(State);
2984  break;
2985  }
2986 
2987  /* Invalid */
2988  default:
2989  {
2990  Fast486Exception(State, FAST486_EXCEPTION_UD);
2991  return;
2992  }
2993  }
2994  }
2995  else
2996  {
2997  /* Only a few of these instructions have any meaning on a 487 */
2998  switch ((ModRegRm.Register << 3) | ModRegRm.SecondRegister)
2999  {
3000  /* FCLEX */
3001  case 0x22:
3002  {
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;
3013 
3014  break;
3015  }
3016 
3017  /* FINIT */
3018  case 0x23:
3019  {
3020  /* Restore the state */
3021  State->FpuControl.Value = FAST486_FPU_DEFAULT_CONTROL;
3022  State->FpuStatus.Value = 0;
3023  State->FpuTag = 0xFFFF;
3024 
3025  break;
3026  }
3027 
3028  /* FENI */
3029  case 0x20:
3030  /* FDISI */
3031  case 0x21:
3032  /* FSETPM */
3033  case 0x24:
3034  /* FRSTPM */
3035  case 0x25:
3036  {
3037  /* These do nothing */
3038  break;
3039  }
3040 
3041  /* Invalid */
3042  default:
3043  {
3044  Fast486Exception(State, FAST486_EXCEPTION_UD);
3045  return;
3046  }
3047  }
3048  }
3049 
3050 #endif
3051 }
3052 
3053 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDC)
3054 {
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;
3060 #endif
3061 
3062  TOGGLE_ADSIZE(AddressSize);
3063 
3064  /* Get the operands */
3065  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
3066  {
3067  /* Exception occurred */
3068  return;
3069  }
3070 
3071  FPU_CHECK();
3072 
3073 #ifndef FAST486_NO_FPU
3074 
3075  Fast486FpuExceptionCheck(State);
3077 
3078  if (ModRegRm.Memory)
3079  {
3080  ULONGLONG Value;
3081 
3082  if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3083  {
3084  /* Raise the invalid operation exception */
3085  State->FpuStatus.Ie = TRUE;
3086 
3087  if (State->FpuControl.Im)
3088  {
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;
3093 
3095  }
3096 
3097  return;
3098  }
3099 
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,
3105  FALSE,
3106  &Value,
3107  sizeof(ULONGLONG)))
3108  {
3109  /* Exception occurred */
3110  return;
3111  }
3112 
3113  Fast486FpuFromDoubleReal(State, Value, &MemoryData);
3114  Operand = &MemoryData;
3115 
3117  }
3118  else
3119  {
3120  /* Load the destination operand from an FPU register */
3121  Operand = &FPU_ST(ModRegRm.SecondRegister);
3122 
3123  if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3124  || (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY))
3125  {
3126  /* Raise the invalid operation exception */
3127  State->FpuStatus.Ie = TRUE;
3128 
3129  if (State->FpuControl.Im)
3130  {
3131  /* Return the indefinite NaN */
3132  Operand->Sign = TRUE;
3133  Operand->Exponent = FPU_MAX_EXPONENT + 1;
3134  Operand->Mantissa = FPU_INDEFINITE_MANTISSA;
3135 
3137  }
3138 
3139  return;
3140  }
3141  }
3142 
3143  /* Perform the requested operation */
3144  Fast486FpuArithmeticOperation(State, ModRegRm.Register, Operand, ModRegRm.Memory);
3145 
3146 #endif
3147 }
3148 
3149 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDD)
3150 {
3151  FAST486_MOD_REG_RM ModRegRm;
3152  BOOLEAN OperandSize, AddressSize;
3153 
3154  OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
3155  TOGGLE_OPSIZE(OperandSize);
3156  TOGGLE_ADSIZE(AddressSize);
3157 
3158  /* Get the operands */
3159  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
3160  {
3161  /* Exception occurred */
3162  return;
3163  }
3164 
3165  FPU_CHECK();
3166 
3167 #ifndef FAST486_NO_FPU
3168 
3169  if (ModRegRm.Memory)
3170  {
3171  switch (ModRegRm.Register)
3172  {
3173  /* FLD */
3174  case 0:
3175  {
3176  ULONGLONG Value;
3177  FAST486_FPU_DATA_REG MemoryData;
3178 
3179  Fast486FpuExceptionCheck(State);
3182 
3183  if (!Fast486ReadMemory(State,
3184  (State->PrefixFlags & FAST486_PREFIX_SEG)
3185  ? State->SegmentOverride : FAST486_REG_DS,
3186  ModRegRm.MemoryAddress,
3187  FALSE,
3188  &Value,
3189  sizeof(ULONGLONG)))
3190  {
3191  /* Exception occurred */
3192  return;
3193  }
3194 
3195  Fast486FpuFromDoubleReal(State, Value, &MemoryData);
3196  Fast486FpuPush(State, &MemoryData);
3197 
3198  break;
3199  }
3200 
3201  /* FST */
3202  case 2:
3203  /* FSTP */
3204  case 3:
3205  {
3207 
3208  Fast486FpuExceptionCheck(State);
3211 
3212  if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3213  {
3214  /* Raise the invalid operation exception */
3215  State->FpuStatus.Ie = TRUE;
3216 
3217  if (!State->FpuControl.Im)
3218  {
3219  return;
3220  }
3221  }
3222  else if (!Fast486FpuToDoubleReal(State, &FPU_ST(0), &Value))
3223  {
3224  /* Exception occurred */
3225  return;
3226  }
3227 
3229  (State->PrefixFlags & FAST486_PREFIX_SEG)
3230  ? State->SegmentOverride : FAST486_REG_DS,
3231  ModRegRm.MemoryAddress,
3232  &Value,
3233  sizeof(ULONGLONG)))
3234  {
3235  /* Exception occurred */
3236  return;
3237  }
3238 
3239  if (ModRegRm.Register == 3) Fast486FpuPop(State);
3240  break;
3241  }
3242 
3243  /* FRSTOR */
3244  case 4:
3245  {
3246  INT i;
3247  UCHAR AllRegs[80];
3248 
3249  /* Save the environment */
3251  (State->PrefixFlags & FAST486_PREFIX_SEG)
3252  ? State->SegmentOverride : FAST486_REG_DS,
3253  ModRegRm.MemoryAddress,
3254  OperandSize))
3255  {
3256  /* Exception occurred */
3257  return;
3258  }
3259 
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,
3265  FALSE,
3266  AllRegs,
3267  sizeof(AllRegs)))
3268  {
3269  /* Exception occurred */
3270  return;
3271  }
3272 
3273  for (i = 0; i < FAST486_NUM_FPU_REGS; i++)
3274  {
3275  State->FpuRegisters[i].Mantissa = *((PULONGLONG)&AllRegs[i * 10]);
3276  State->FpuRegisters[i].Exponent = *((PUSHORT)&AllRegs[(i * 10) + sizeof(ULONGLONG)]) & 0x7FFF;
3277 
3278  if (*((PUSHORT)&AllRegs[(i * 10) + sizeof(ULONGLONG)]) & 0x8000)
3279  {
3280  State->FpuRegisters[i].Sign = TRUE;
3281  }
3282  else
3283  {
3284  State->FpuRegisters[i].Sign = FALSE;
3285  }
3286  }
3287 
3288  break;
3289  }
3290 
3291  /* FSAVE */
3292  case 6:
3293  {
3294  INT i;
3295  UCHAR AllRegs[80];
3296 
3297  /* Save the environment */
3299  (State->PrefixFlags & FAST486_PREFIX_SEG)
3300  ? State->SegmentOverride : FAST486_REG_DS,
3301  ModRegRm.MemoryAddress,
3302  OperandSize))
3303  {
3304  /* Exception occurred */
3305  return;
3306  }
3307 
3308  /* Save the registers */
3309  for (i = 0; i < FAST486_NUM_FPU_REGS; i++)
3310  {
3311  *((PULONGLONG)&AllRegs[i * 10]) = State->FpuRegisters[i].Mantissa;
3312  *((PUSHORT)&AllRegs[(i * 10) + sizeof(ULONGLONG)]) = State->FpuRegisters[i].Exponent;
3313 
3314  if (State->FpuRegisters[i].Sign)
3315  {
3316  *((PUSHORT)&AllRegs[(i * 10) + sizeof(ULONGLONG)]) |= 0x8000;
3317  }
3318  }
3319 
3321  (State->PrefixFlags & FAST486_PREFIX_SEG)
3322  ? State->SegmentOverride : FAST486_REG_DS,
3323  ModRegRm.MemoryAddress + (OperandSize + 1) * 14,
3324  AllRegs,
3325  sizeof(AllRegs));
3326 
3327  break;
3328  }
3329 
3330  /* FSTSW */
3331  case 7:
3332  {
3333  Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, State->FpuStatus.Value);
3334  break;
3335  }
3336 
3337  /* Invalid */
3338  default:
3339  {
3340  Fast486Exception(State, FAST486_EXCEPTION_UD);
3341  }
3342  }
3343  }
3344  else
3345  {
3346  switch (ModRegRm.Register)
3347  {
3348  /* FFREE */
3349  case 0:
3350  {
3352  break;
3353  }
3354 
3355  /* FXCH */
3356  case 1:
3357  {
3358  FAST486_FPU_DATA_REG Temp;
3359 
3361  Fast486FpuExceptionCheck(State);
3362 
3363  if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3364  || FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
3365  {
3366  State->FpuStatus.Ie = TRUE;
3367  break;
3368  }
3369 
3370  /* Exchange */
3371  Temp = FPU_ST(0);
3372  FPU_ST(0) = FPU_ST(ModRegRm.SecondRegister);
3373  FPU_ST(ModRegRm.SecondRegister) = Temp;
3374 
3375  FPU_UPDATE_TAG(0);
3376  FPU_UPDATE_TAG(ModRegRm.SecondRegister);
3377 
3378  break;
3379  }
3380 
3381  /* FST */
3382  case 2:
3383  /* FSTP */
3384  case 3:
3385  {
3387  Fast486FpuExceptionCheck(State);
3388 
3389  FPU_ST(ModRegRm.SecondRegister) = FPU_ST(0);
3390  FPU_UPDATE_TAG(ModRegRm.SecondRegister);
3391 
3392  if (ModRegRm.Register == 3) Fast486FpuPop(State);
3393  break;
3394  }
3395 
3396  /* FUCOM */
3397  case 4:
3398  /* FUCOMP */
3399  case 5:
3400  {
3402  Fast486FpuExceptionCheck(State);
3403 
3404  if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3405  || (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY))
3406  {
3407  State->FpuStatus.Ie = TRUE;
3408  return;
3409  }
3410 
3412  if (ModRegRm.Register == 5) Fast486FpuPop(State);
3413 
3414  break;
3415  }
3416 
3417  /* Invalid */
3418  default:
3419  {
3420  Fast486Exception(State, FAST486_EXCEPTION_UD);
3421  }
3422  }
3423  }
3424 
3425 #endif
3426 }
3427 
3428 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDE)
3429 {
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;
3435 #endif
3436 
3437  TOGGLE_ADSIZE(AddressSize);
3438 
3439  /* Get the operands */
3440  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
3441  {
3442  /* Exception occurred */
3443  return;
3444  }
3445 
3446  FPU_CHECK();
3447 
3448 #ifndef FAST486_NO_FPU
3449 
3451  Fast486FpuExceptionCheck(State);
3452 
3453  if (ModRegRm.Memory)
3454  {
3455  SHORT Value;
3456 
3457  if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3458  {
3459  /* Raise the invalid operation exception */
3460  State->FpuStatus.Ie = TRUE;
3461 
3462  if (State->FpuControl.Im)
3463  {
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;
3468 
3470  }
3471 
3472  return;
3473  }
3474 
3475  /* Load the source operand from memory */
3476  if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, (PUSHORT)&Value))
3477  {
3478  /* Exception occurred */
3479  return;
3480  }
3481 
3482  Fast486FpuFromInteger(State, (LONGLONG)Value, &MemoryData);
3483  Operand = &MemoryData;
3484 
3486  }
3487  else
3488  {
3489  /* FCOMPP check */
3490  if ((ModRegRm.Register == 3) && (ModRegRm.SecondRegister != 1))
3491  {
3492  /* Invalid */
3493  Fast486Exception(State, FAST486_EXCEPTION_UD);
3494  return;
3495  }
3496 
3497  /* Load the destination operand from a register */
3498  Operand = &FPU_ST(ModRegRm.SecondRegister);
3499 
3500  if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3501  || (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY))
3502  {
3503  /* Raise the invalid operation exception, if unmasked */
3504  State->FpuStatus.Ie = TRUE;
3505  return;
3506  }
3507  }
3508 
3509  /* Perform the requested operation */
3510  Fast486FpuArithmeticOperation(State, ModRegRm.Register, Operand, ModRegRm.Memory);
3511  if (!ModRegRm.Memory) Fast486FpuPop(State);
3512 
3513 #endif
3514 }
3515 
3516 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF)
3517 {
3518  FAST486_MOD_REG_RM ModRegRm;
3519  BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
3520 
3521  TOGGLE_ADSIZE(AddressSize);
3522 
3523  /* Get the operands */
3524  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
3525  {
3526  /* Exception occurred */
3527  return;
3528  }
3529 
3530  FPU_CHECK();
3531 
3532 #ifndef FAST486_NO_FPU
3533 
3535  Fast486FpuExceptionCheck(State);
3536 
3537  if (ModRegRm.Memory)
3538  {
3540 
3541  switch (ModRegRm.Register)
3542  {
3543  /* FILD */
3544  case 0:
3545  {
3546  SHORT Value;
3547  FAST486_FPU_DATA_REG Temp;
3548 
3549  if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, (PUSHORT)&Value))
3550  {
3551  /* Exception occurred */
3552  return;
3553  }
3554 
3556  Fast486FpuPush(State, &Temp);
3557 
3558  break;
3559  }
3560 
3561  /* FIST */
3562  case 2:
3563  /* FISTP */
3564  case 3:
3565  {
3566  LONGLONG Temp = 0LL;
3567 
3568  if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL))
3569  {
3570  /* Raise the invalid operation exception */
3571  State->FpuStatus.Ie = TRUE;
3572 
3573  if (!State->FpuControl.Im)
3574  {
3575  return;
3576  }
3577  }
3578 
3579  if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp))
3580  {
3581  /* Exception occurred */
3582  return;
3583  }
3584 
3585  /* Check if it can fit in a signed 16-bit integer */
3586  if ((LONGLONG)((SHORT)Temp) != Temp)
3587  {
3588  /* Raise the invalid operation exception */
3589  State->FpuStatus.Ie = TRUE;
3590 
3591  if (State->FpuControl.Im)
3592  {
3593  Temp = 0x8000LL;
3594  }
3595  else
3596  {
3597  return;
3598  }
3599  }
3600 
3601  if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, (USHORT)((SHORT)Temp)))
3602  {
3603  /* Exception occurred */
3604  return;
3605  }
3606 
3607  if (ModRegRm.Register == 3)
3608  {
3609  /* Pop the FPU stack too */
3610  Fast486FpuPop(State);
3611  }
3612 
3613  break;
3614  }
3615 
3616  /* FBLD */
3617  case 4:
3618  {
3619  FAST486_FPU_DATA_REG Value;
3620  UCHAR Buffer[10];
3621 
3622  if (!Fast486ReadMemory(State,
3623  (State->PrefixFlags & FAST486_PREFIX_SEG)
3624  ? State->SegmentOverride : FAST486_REG_DS,
3625  ModRegRm.MemoryAddress,
3626  FALSE,
3627  Buffer,
3628  sizeof(Buffer)))
3629  {
3630  /* Exception occurred */
3631  return;
3632  }
3633 
3635  Fast486FpuPush(State, &Value);
3636 
3637  break;
3638  }
3639 
3640  /* FILD (64-bit int) */
3641  case 5:
3642  {
3643  LONGLONG Value;
3644  FAST486_FPU_DATA_REG Temp;
3645 
3646  if (!Fast486ReadMemory(State,
3647  (State->PrefixFlags & FAST486_PREFIX_SEG)
3648  ? State->SegmentOverride : FAST486_REG_DS,
3649  ModRegRm.MemoryAddress,
3650  FALSE,
3651  &Value,
3652  sizeof(LONGLONG)))
3653  {
3654  /* Exception occurred */
3655  return;
3656  }
3657 
3659  Fast486FpuPush(State, &Temp);
3660 
3661  break;
3662  }
3663 
3664  /* FBSTP */
3665  case 6:
3666  {
3667  UCHAR Buffer[10] = {0};
3668 
3669  if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3670  {
3671  /* Raise the invalid operation exception */
3672  State->FpuStatus.Ie = TRUE;
3673 
3674  if (!State->FpuControl.Im)
3675  {
3676  return;
3677  }
3678  }
3679  else if (!Fast486FpuToPackedBcd(State, &FPU_ST(0), Buffer))
3680  {
3681  /* Exception occurred */
3682  return;
3683  }
3684 
3686  (State->PrefixFlags & FAST486_PREFIX_SEG)
3687  ? State->SegmentOverride : FAST486_REG_DS,
3688  ModRegRm.MemoryAddress,
3689  Buffer,
3690  sizeof(Buffer)))
3691  {
3692  /* Exception occurred */
3693  return;
3694  }
3695 
3696  Fast486FpuPop(State);
3697  break;
3698  }
3699 
3700  /* FISTP (64-bit int) */
3701  case 7:
3702  {
3703  LONGLONG Temp = 0LL;
3704 
3705  if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL))
3706  {
3707  /* Raise the invalid operation exception */
3708  State->FpuStatus.Ie = TRUE;
3709 
3710  if (!State->FpuControl.Im)
3711  {
3712  return;
3713  }
3714  }
3715 
3716  if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp))
3717  {
3718  /* Exception occurred */
3719  return;
3720  }
3721 
3723  (State->PrefixFlags & FAST486_PREFIX_SEG)
3724  ? State->SegmentOverride : FAST486_REG_DS,
3725  ModRegRm.MemoryAddress,
3726  &Temp,
3727  sizeof(LONGLONG)))
3728  {
3729  /* Exception occurred */
3730  return;
3731  }
3732 
3733  /* Pop the FPU stack too */
3734  Fast486FpuPop(State);
3735 
3736  break;
3737  }
3738 
3739  /* Invalid */
3740  default:
3741  {
3742  Fast486Exception(State, FAST486_EXCEPTION_UD);
3743  }
3744  }
3745  }
3746  else
3747  {
3748  switch (ModRegRm.Register)
3749  {
3750  /* FFREEP */
3751  case 0:
3752  {
3754  Fast486FpuPop(State);
3755 
3756  break;
3757  }
3758 
3759  /* FXCH */
3760  case 1:
3761  {
3762  FAST486_FPU_DATA_REG Temp;
3763 
3764  if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3765  || FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
3766  {
3767  State->FpuStatus.Ie = TRUE;
3768  break;
3769  }
3770 
3771  /* Exchange */
3772  Temp = FPU_ST(0);
3773  FPU_ST(0) = FPU_ST(ModRegRm.SecondRegister);
3774  FPU_ST(ModRegRm.SecondRegister) = Temp;
3775 
3776  FPU_UPDATE_TAG(0);
3777  FPU_UPDATE_TAG(ModRegRm.SecondRegister);
3778 
3779  break;
3780  }
3781 
3782  /* FSTP */
3783  case 2:
3784  case 3:
3785  {
3786  FPU_ST(ModRegRm.SecondRegister) = FPU_ST(0);
3787  FPU_UPDATE_TAG(ModRegRm.SecondRegister);
3788  Fast486FpuPop(State);
3789 
3790  break;
3791  }
3792 
3793  /* FSTSW */
3794  case 4:
3795  {
3796  if (ModRegRm.SecondRegister != 0)
3797  {
3798  /* Invalid */
3799  Fast486Exception(State, FAST486_EXCEPTION_UD);
3800  return;
3801  }
3802 
3803  /* Store the status word in AX */
3804  State->GeneralRegs[FAST486_REG_EAX].LowWord = State->FpuStatus.Value;
3805 
3806  break;
3807  }
3808 
3809  /* Invalid */
3810  default:
3811  {
3812  Fast486Exception(State, FAST486_EXCEPTION_UD);
3813  return;
3814  }
3815  }
3816  }
3817 
3818 #endif
3819 }
3820 
3821 /* EOF */
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2327
#define max(a, b)
Definition: svc.c:63
#define FPU_ST(i)
Definition: fpu.h:37
static VOID FASTCALL Fast486FpuFromDoubleReal(PFAST486_STATE State, ULONGLONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:631
#define TRUE
Definition: types.h:120
#define LL
Definition: tui.h:72
static const FAST486_FPU_DATA_REG FpuL2Ten
Definition: fpu.c:45
#define FPU_IS_NORMALIZED(x)
Definition: fpu.h:66
#define FPU_IS_ZERO(x)
Definition: fpu.h:67
static BOOLEAN FASTCALL Fast486FpuSaveEnvironment(PFAST486_STATE State, INT Segment, ULONG Address, BOOLEAN Size)
Definition: fpu.c:1768
#define FPU_REAL8_BIAS
Definition: fpu.h:56
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
unsigned char * PUCHAR
Definition: retypes.h:3
static VOID FASTCALL Fast486FpuFromSingleReal(PFAST486_STATE State, ULONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:533
#define FPU_IS_INDEFINITE(x)
Definition: fpu.h:72
static const FAST486_FPU_DATA_REG FpuLgTwo
Definition: fpu.c:51
static const FAST486_FPU_DATA_REG FpuZero
Definition: fpu.c:36
Definition: msg.c:1064
static VOID FASTCALL Fast486FpuCalculateTwoPowerMinusOne(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1217
#define FPU_IS_POS_INF(x)
Definition: fpu.h:70
FAST486_GEN_REGS Register
Definition: common.h:76
#define FASTCALL
Definition: nt_native.h:50
#define FPU_REAL8_INFINITY
Definition: fpu.h:63
int32_t INT
Definition: typedefs.h:56
#define FPU_UPDATE_TAG(i)
Definition: fpu.h:44
#define FPU_REAL8_INDEFINITE
Definition: fpu.h:64
static VOID FASTCALL Fast486FpuCompare(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand)
Definition: fpu.c:943
__GNU_EXTENSION typedef __int64 * PLONGLONG
Definition: ntbasedef.h:389
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static BOOLEAN FASTCALL Fast486FpuCalculateLogBase2(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1265
static BOOLEAN FASTCALL Fast486FpuDivide(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1105
long LONG
Definition: pedump.c:60
short SHORT
Definition: pedump.c:59
static BOOLEAN FASTCALL Fast486FpuToDoubleReal(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PULONGLONG Result)
Definition: fpu.c:652
#define FPU_INDEFINITE_MANTISSA
Definition: fpu.h:60
#define FPU_CHECK()
Definition: fpu.h:31
static BOOLEAN FASTCALL Fast486FpuToSingleReal(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PULONG Result)
Definition: fpu.c:554
static BOOLEAN FASTCALL Fast486FpuToInteger(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PLONGLONG Result)
Definition: fpu.c:467
static VOID FASTCALL Fast486FpuRound(PFAST486_STATE State, PULONGLONG Result, BOOLEAN Sign, ULONGLONG Remainder, INT RemainderHighBit)
Definition: fpu.c:398
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
static WCHAR Address[46]
Definition: ping.c:68
#define FPU_IS_NEG_INF(x)
Definition: fpu.h:71
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8)
Definition: fpu.c:1808
Definition: bufpool.h:45
#define FPU_SAVE_LAST_INST()
Definition: fpu.h:45
#define ULL(a, b)
Definition: format_msg.c:27
_Inout_ PVOID Segment
Definition: exfuncs.h:893
int64_t LONGLONG
Definition: typedefs.h:66
#define TOGGLE_ADSIZE(x)
Definition: common.h:53
static const FAST486_FPU_DATA_REG FpuInverseNumberAtan[INVERSE_NUMBERS_COUNT]
Definition: fpu.c:224
static BOOLEAN FASTCALL Fast486FpuRemainder(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand, BOOLEAN RoundToNearest, PFAST486_FPU_DATA_REG Result OPTIONAL, PLONGLONG Quotient OPTIONAL)
Definition: fpu.c:1352
static BOOLEAN FASTCALL Fast486FpuMultiply(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1000
static BOOLEAN FASTCALL Fast486FpuSubtract(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:928
BOOLEAN FASTCALL Fast486WriteMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, PVOID Buffer, ULONG Size)
Definition: common.c:163
#define FPU_IS_INFINITY(x)
Definition: fpu.h:69
if(!(yy_init))
Definition: macro.lex.yy.c:714
uint64_t ULONGLONG
Definition: typedefs.h:65
static ULONGLONG UnsignedDivMod128(ULONGLONG DividendLow, ULONGLONG DividendHigh, ULONGLONG Divisor, PULONGLONG QuotientLow, PULONGLONG QuotientHigh)
Definition: fpu.c:315
FAST486_GEN_REGS SecondRegister
Definition: common.h:80
static BOOLEAN FASTCALL Fast486FpuToPackedBcd(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PUCHAR Result)
Definition: fpu.c:747
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define FPU_MANTISSA_HIGH_BIT
Definition: fpu.h:59
#define FPU_REAL4_INDEFINITE
Definition: fpu.h:62
unsigned char UCHAR
Definition: xmlstorage.h:181
#define FPU_REAL10_BIAS
Definition: fpu.h:57
static BOOLEAN FASTCALL Fast486FpuAdd(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:773
#define FAST486_FPU_DEFAULT_CONTROL
Definition: fast486.h:105
#define FPU_MAX_EXPONENT
Definition: fpu.h:58
static VOID FASTCALL Fast486FpuFromInteger(PFAST486_STATE State, LONGLONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:444
#define FPU_IS_NAN(x)
Definition: fpu.h:68
#define INVERSE_NUMBERS_COUNT
Definition: fpu.h:74
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
static const WCHAR Cleanup[]
Definition: register.c:80
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:204
static VOID FASTCALL Fast486FpuArithmeticOperation(PFAST486_STATE State, INT Operation, PFAST486_FPU_DATA_REG Operand, BOOLEAN TopDestination)
Definition: fpu.c:1484
BOOLEAN FASTCALL Fast486ReadMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, BOOLEAN InstFetch, PVOID Buffer, ULONG Size)
Definition: common.c:36
static VOID FASTCALL Fast486FpuFromPackedBcd(PFAST486_STATE State, PUCHAR Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:726
static const FAST486_FPU_DATA_REG FpuLnTwo
Definition: fpu.c:54
static BOOLEAN FASTCALL Fast486FpuCalculateArcTangent(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Numerator, PCFAST486_FPU_DATA_REG Denominator, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1613
#define FPU_SET_TAG(i, t)
Definition: fpu.h:40
#define FAST486_PREFIX_SEG
Definition: fast486.h:98
static ULONGLONG UnsignedMult128(ULONGLONG Multiplicand, ULONGLONG Multiplier, ULONGLONG *HighProduct)
Definition: fpu.c:283
static const FAST486_FPU_DATA_REG FpuPi
Definition: fpu.c:42
#define TOGGLE_OPSIZE(x)
Definition: common.h:50
unsigned short USHORT
Definition: pedump.c:61
static const FAST486_FPU_DATA_REG FpuInverseNumber[INVERSE_NUMBERS_COUNT]
Definition: fpu.c:62
unsigned int * PULONG
Definition: retypes.h:1
#define FPU_SAVE_LAST_OPERAND()
Definition: fpu.h:49
#define FPU_REAL4_BIAS
Definition: fpu.h:55
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:390
static const FAST486_FPU_DATA_REG FpuOne
Definition: fpu.c:39
_In_ LARGE_INTEGER Divisor
Definition: rtlfuncs.h:3046
#define FAST486_NUM_FPU_REGS
Definition: fast486.h:44
unsigned int ULONG
Definition: retypes.h:1
_In_ FLT_SET_CONTEXT_OPERATION Operation
Definition: fltkernel.h:1468
#define FPU_GET_TAG(i)
Definition: fpu.h:39
static const FAST486_FPU_DATA_REG FpuInverseNumberCosine[INVERSE_NUMBERS_COUNT]
Definition: fpu.c:170
#define FPU_REAL4_INFINITY
Definition: fpu.h:61
static const FAST486_FPU_DATA_REG FpuTwo
Definition: fpu.c:57
static BOOLEAN FASTCALL Fast486FpuCalculateSquareRoot(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1557
ULONG MemoryAddress
Definition: common.h:81
static BOOLEAN FASTCALL Fast486FpuCalculateCosine(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1470
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
static BOOLEAN FASTCALL Fast486FpuLoadEnvironment(PFAST486_STATE State, INT Segment, ULONG Address, BOOLEAN Size)
Definition: fpu.c:1725
unsigned short * PUSHORT
Definition: retypes.h:2
static BOOLEAN FASTCALL Fast486FpuCalculateSine(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1390
static const FAST486_FPU_DATA_REG FpuL2E
Definition: fpu.c:48
static const FAST486_FPU_DATA_REG FpuHalfPi
Definition: fpu.c:60
_In_ LARGE_INTEGER _Out_opt_ PLARGE_INTEGER Remainder
Definition: rtlfuncs.h:3046
BOOLEAN Memory
Definition: common.h:77
static const FAST486_FPU_DATA_REG FpuInverseNumberSine[INVERSE_NUMBERS_COUNT]
Definition: fpu.c:116
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68