ReactOS 0.4.15-dev-7931-gfd331f1
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 */
36static const FAST486_FPU_DATA_REG FpuZero = {0ULL, 0, FALSE};
37
38/* 1.00 */
39static const FAST486_FPU_DATA_REG FpuOne = {0x8000000000000000ULL, FPU_REAL10_BIAS, FALSE};
40
41/* Pi */
42static const FAST486_FPU_DATA_REG FpuPi = {0xC90FDAA22168C235ULL, FPU_REAL10_BIAS + 1, FALSE};
43
44/* lb(10) */
45static const FAST486_FPU_DATA_REG FpuL2Ten = {0xD49A784BCD1B8AFEULL, FPU_REAL10_BIAS + 1, FALSE};
46
47/* lb(e) */
48static const FAST486_FPU_DATA_REG FpuL2E = {0xB8AA3B295C17F0BCULL, FPU_REAL10_BIAS, FALSE};
49
50/* lg(2) */
51static const FAST486_FPU_DATA_REG FpuLgTwo = {0x9A209A84FBCFF799ULL, FPU_REAL10_BIAS - 2, FALSE};
52
53/* ln(2) */
54static const FAST486_FPU_DATA_REG FpuLnTwo = {0xB17217F7D1CF79ACULL, FPU_REAL10_BIAS - 1, FALSE};
55
56/* 2.00 */
57static const FAST486_FPU_DATA_REG FpuTwo = {0x8000000000000000ULL, FPU_REAL10_BIAS + 1, FALSE};
58
59/* Pi / 2 */
60static const FAST486_FPU_DATA_REG FpuHalfPi = {0xC90FDAA22168C235ULL, FPU_REAL10_BIAS, FALSE};
61
62static 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
116static 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
170static 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
224static 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
282static 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
314static 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
397static inline VOID FASTCALL
398Fast486FpuRound(PFAST486_STATE State,
402 INT RemainderHighBit)
403{
404 switch (State->FpuControl.Rc)
405 {
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
443static inline VOID FASTCALL
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
466static inline BOOLEAN FASTCALL
468 PCFAST486_FPU_DATA_REG Value,
470{
471 ULONG Bits;
473 SHORT UnbiasedExp = (SHORT)Value->Exponent - FPU_REAL10_BIAS;
474
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 */
527
528 if (Value->Sign) *Result = -*Result;
529 return TRUE;
530}
531
532static 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
553static inline BOOLEAN FASTCALL
555 PCFAST486_FPU_DATA_REG Value,
557{
559 SHORT UnbiasedExp = (SHORT)Value->Exponent - FPU_REAL10_BIAS;
560 ULONGLONG Result64;
561
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
624SetSign:
625
626 if (Value->Sign) *Result |= 0x80000000;
627 return TRUE;
628}
629
630static 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
651static inline BOOLEAN FASTCALL
653 PCFAST486_FPU_DATA_REG Value,
655{
657 SHORT UnbiasedExp = (SHORT)Value->Exponent - FPU_REAL10_BIAS;
658
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
719SetSign:
720
721 if (Value->Sign) *Result |= 1ULL << 63;
722 return TRUE;
723}
724
725static inline VOID FASTCALL
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
746static inline BOOLEAN FASTCALL
748 PCFAST486_FPU_DATA_REG Value,
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
772static inline BOOLEAN FASTCALL
773Fast486FpuAdd(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;
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
927static inline BOOLEAN FASTCALL
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
942static inline VOID FASTCALL
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
999static inline BOOLEAN FASTCALL
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
1104static inline BOOLEAN FASTCALL
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 */
1216static 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
1264static 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 */
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
1351static 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{
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
1380Cleanup:
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 */
1389static 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 */
1469static 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
1483static 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 */
1556static 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 */
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 */
1612static 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
1724static 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 {
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
1767static 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 {
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
1808FAST486_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
1897FAST486_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)
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);
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);
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 */
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 */
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
2735FAST486_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 */
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
2821FAST486_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
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
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
3053FAST486_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 {
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 */
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
3149FAST486_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 {
3177 FAST486_FPU_DATA_REG MemoryData;
3178
3179 Fast486FpuExceptionCheck(State);
3182
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 */
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)
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);
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);
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
3428FAST486_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
3516FAST486_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
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
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 {
3644 FAST486_FPU_DATA_REG Temp;
3645
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
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)
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);
3778
3779 break;
3780 }
3781
3782 /* FSTP */
3783 case 2:
3784 case 3:
3785 {
3786 FPU_ST(ModRegRm.SecondRegister) = FPU_ST(0);
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 */
unsigned char BOOLEAN
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
@ Sign
Definition: msg.c:1064
static const WCHAR Cleanup[]
Definition: register.c:80
@ Success
Definition: eventcreate.c:712
#define FAST486_NUM_FPU_REGS
Definition: fast486.h:44
#define FAST486_PREFIX_SEG
Definition: fast486.h:98
#define FAST486_FPU_DEFAULT_CONTROL
Definition: fast486.h:105
FP_OP Operation
Definition: fpcontrol.c:150
static VOID FASTCALL Fast486FpuArithmeticOperation(PFAST486_STATE State, INT Operation, PFAST486_FPU_DATA_REG Operand, BOOLEAN TopDestination)
Definition: fpu.c:1484
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
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 Fast486FpuToSingleReal(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PULONG Result)
Definition: fpu.c:554
static VOID FASTCALL Fast486FpuFromPackedBcd(PFAST486_STATE State, PUCHAR Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:726
static const FAST486_FPU_DATA_REG FpuOne
Definition: fpu.c:39
static const FAST486_FPU_DATA_REG FpuInverseNumberSine[INVERSE_NUMBERS_COUNT]
Definition: fpu.c:116
static const FAST486_FPU_DATA_REG FpuInverseNumber[INVERSE_NUMBERS_COUNT]
Definition: fpu.c:62
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 FpuLgTwo
Definition: fpu.c:51
static BOOLEAN FASTCALL Fast486FpuCalculateSquareRoot(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1557
static BOOLEAN FASTCALL Fast486FpuCalculateCosine(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1470
static BOOLEAN FASTCALL Fast486FpuToPackedBcd(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PUCHAR Result)
Definition: fpu.c:747
static VOID FASTCALL Fast486FpuCompare(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand)
Definition: fpu.c:943
static ULONGLONG UnsignedMult128(ULONGLONG Multiplicand, ULONGLONG Multiplier, ULONGLONG *HighProduct)
Definition: fpu.c:283
static const FAST486_FPU_DATA_REG FpuZero
Definition: fpu.c:36
static VOID FASTCALL Fast486FpuFromDoubleReal(PFAST486_STATE State, ULONGLONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:631
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
static VOID FASTCALL Fast486FpuCalculateTwoPowerMinusOne(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1217
static ULONGLONG UnsignedDivMod128(ULONGLONG DividendLow, ULONGLONG DividendHigh, ULONGLONG Divisor, PULONGLONG QuotientLow, PULONGLONG QuotientHigh)
Definition: fpu.c:315
static const FAST486_FPU_DATA_REG FpuL2E
Definition: fpu.c:48
static BOOLEAN FASTCALL Fast486FpuCalculateLogBase2(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1265
static const FAST486_FPU_DATA_REG FpuLnTwo
Definition: fpu.c:54
static BOOLEAN FASTCALL Fast486FpuLoadEnvironment(PFAST486_STATE State, INT Segment, ULONG Address, BOOLEAN Size)
Definition: fpu.c:1725
static BOOLEAN FASTCALL Fast486FpuToDoubleReal(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PULONGLONG Result)
Definition: fpu.c:652
static const FAST486_FPU_DATA_REG FpuTwo
Definition: fpu.c:57
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 Fast486FpuToInteger(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PLONGLONG Result)
Definition: fpu.c:467
static VOID FASTCALL Fast486FpuFromInteger(PFAST486_STATE State, LONGLONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:444
static const FAST486_FPU_DATA_REG FpuL2Ten
Definition: fpu.c:45
static const FAST486_FPU_DATA_REG FpuInverseNumberCosine[INVERSE_NUMBERS_COUNT]
Definition: fpu.c:170
static VOID FASTCALL Fast486FpuRound(PFAST486_STATE State, PULONGLONG Result, BOOLEAN Sign, ULONGLONG Remainder, INT RemainderHighBit)
Definition: fpu.c:398
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
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
static VOID FASTCALL Fast486FpuFromSingleReal(PFAST486_STATE State, ULONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:533
static const FAST486_FPU_DATA_REG FpuHalfPi
Definition: fpu.c:60
static BOOLEAN FASTCALL Fast486FpuSaveEnvironment(PFAST486_STATE State, INT Segment, ULONG Address, BOOLEAN Size)
Definition: fpu.c:1768
static const FAST486_FPU_DATA_REG FpuInverseNumberAtan[INVERSE_NUMBERS_COUNT]
Definition: fpu.c:224
static const FAST486_FPU_DATA_REG FpuPi
Definition: fpu.c:42
#define FPU_SAVE_LAST_OPERAND()
Definition: fpu.h:49
#define FPU_IS_POS_INF(x)
Definition: fpu.h:70
#define FPU_INDEFINITE_MANTISSA
Definition: fpu.h:60
#define FPU_REAL4_INDEFINITE
Definition: fpu.h:62
#define FPU_REAL8_INDEFINITE
Definition: fpu.h:64
@ FPU_ROUND_UP
Definition: fpu.h:95
@ FPU_ROUND_TRUNCATE
Definition: fpu.h:96
@ FPU_ROUND_NEAREST
Definition: fpu.h:93
@ FPU_ROUND_DOWN
Definition: fpu.h:94
#define FPU_UPDATE_TAG(i)
Definition: fpu.h:44
#define FPU_CHECK()
Definition: fpu.h:31
#define INVERSE_NUMBERS_COUNT
Definition: fpu.h:74
#define FPU_REAL8_BIAS
Definition: fpu.h:56
#define FPU_GET_TAG(i)
Definition: fpu.h:39
#define FPU_IS_NAN(x)
Definition: fpu.h:68
#define FPU_SAVE_LAST_INST()
Definition: fpu.h:45
#define FPU_REAL4_INFINITY
Definition: fpu.h:61
#define FPU_IS_ZERO(x)
Definition: fpu.h:67
@ FPU_TAG_SPECIAL
Definition: fpu.h:87
@ FPU_TAG_EMPTY
Definition: fpu.h:88
@ FPU_TAG_ZERO
Definition: fpu.h:86
#define FPU_IS_NORMALIZED(x)
Definition: fpu.h:66
#define FPU_REAL4_BIAS
Definition: fpu.h:55
#define FPU_SET_TAG(i, t)
Definition: fpu.h:40
#define FPU_IS_INDEFINITE(x)
Definition: fpu.h:72
#define FPU_IS_NEG_INF(x)
Definition: fpu.h:71
#define FPU_ST(i)
Definition: fpu.h:37
#define FPU_REAL8_INFINITY
Definition: fpu.h:63
#define FPU_IS_INFINITY(x)
Definition: fpu.h:69
#define FPU_MAX_EXPONENT
Definition: fpu.h:58
#define FPU_MANTISSA_HIGH_BIT
Definition: fpu.h:59
#define FPU_REAL10_BIAS
Definition: fpu.h:57
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
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
#define ULL(a, b)
Definition: format_msg.c:27
#define FASTCALL
Definition: nt_native.h:50
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:383
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
__GNU_EXTENSION typedef __int64 * PLONGLONG
Definition: ntbasedef.h:382
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:207
#define FAST486_OPCODE_HANDLER(x)
Definition: opcodes.h:31
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
static WCHAR Address[46]
Definition: ping.c:68
@ Inverse
Definition: sacdrv.h:1385
BOOLEAN FASTCALL Fast486WriteMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, PVOID Buffer, ULONG Size)
Definition: common.c:163
BOOLEAN FASTCALL Fast486ReadMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, BOOLEAN InstFetch, PVOID Buffer, ULONG Size)
Definition: common.c:36
#define TOGGLE_ADSIZE(x)
Definition: common.h:53
#define TOGGLE_OPSIZE(x)
Definition: common.h:50
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
FAST486_GEN_REGS SecondRegister
Definition: common.h:80
ULONG MemoryAddress
Definition: common.h:81
BOOLEAN Memory
Definition: common.h:77
FAST486_GEN_REGS Register
Definition: common.h:76
#define max(a, b)
Definition: svc.c:63
#define LL
Definition: tui.h:167
uint32_t * PULONG
Definition: typedefs.h:59
int64_t LONGLONG
Definition: typedefs.h:68
int32_t INT
Definition: typedefs.h:58
uint16_t * PUSHORT
Definition: typedefs.h:56
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_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:409
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
_In_ LARGE_INTEGER Divisor
Definition: rtlfuncs.h:3044
_In_ LARGE_INTEGER _Out_opt_ PLARGE_INTEGER Remainder
Definition: rtlfuncs.h:3045
unsigned char UCHAR
Definition: xmlstorage.h:181