1 /* 2 * Fast486 386/486 CPU Emulation Library 3 * fpu.c 4 * 5 * Copyright (C) 2015 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 */ 21 22 /* INCLUDES *******************************************************************/ 23 24 #include <windef.h> 25 26 // #define NDEBUG 27 #include <debug.h> 28 29 #include <fast486.h> 30 #include "common.h" 31 #include "fpu.h" 32 33 /* CONSTANTS ******************************************************************/ 34 35 /* 0.00 */ 36 static const FAST486_FPU_DATA_REG FpuZero = {0ULL, 0, FALSE}; 37 38 /* 1.00 */ 39 static const FAST486_FPU_DATA_REG FpuOne = {0x8000000000000000ULL, FPU_REAL10_BIAS, FALSE}; 40 41 /* Pi */ 42 static const FAST486_FPU_DATA_REG FpuPi = {0xC90FDAA22168C235ULL, FPU_REAL10_BIAS + 1, FALSE}; 43 44 /* lb(10) */ 45 static const FAST486_FPU_DATA_REG FpuL2Ten = {0xD49A784BCD1B8AFEULL, FPU_REAL10_BIAS + 1, FALSE}; 46 47 /* lb(e) */ 48 static const FAST486_FPU_DATA_REG FpuL2E = {0xB8AA3B295C17F0BCULL, FPU_REAL10_BIAS, FALSE}; 49 50 /* lg(2) */ 51 static const FAST486_FPU_DATA_REG FpuLgTwo = {0x9A209A84FBCFF799ULL, FPU_REAL10_BIAS - 2, FALSE}; 52 53 /* ln(2) */ 54 static const FAST486_FPU_DATA_REG FpuLnTwo = {0xB17217F7D1CF79ACULL, FPU_REAL10_BIAS - 1, FALSE}; 55 56 /* 2.00 */ 57 static const FAST486_FPU_DATA_REG FpuTwo = {0x8000000000000000ULL, FPU_REAL10_BIAS + 1, FALSE}; 58 59 /* Pi / 2 */ 60 static const FAST486_FPU_DATA_REG FpuHalfPi = {0xC90FDAA22168C235ULL, FPU_REAL10_BIAS, FALSE}; 61 62 static const FAST486_FPU_DATA_REG FpuInverseNumber[INVERSE_NUMBERS_COUNT] = 63 { 64 {0x8000000000000000ULL, FPU_REAL10_BIAS, FALSE}, /* 1 / 1 */ 65 {0x8000000000000000ULL, FPU_REAL10_BIAS - 1, FALSE}, /* 1 / 2 */ 66 {0xAAAAAAAAAAAAAAABULL, FPU_REAL10_BIAS - 2, FALSE}, /* 1 / 3 */ 67 {0x8000000000000000ULL, FPU_REAL10_BIAS - 2, FALSE}, /* 1 / 4 */ 68 {0xCCCCCCCCCCCCCCCDULL, FPU_REAL10_BIAS - 3, FALSE}, /* 1 / 5 */ 69 {0xAAAAAAAAAAAAAAAAULL, FPU_REAL10_BIAS - 3, FALSE}, /* 1 / 6 */ 70 {0x9249249249249249ULL, FPU_REAL10_BIAS - 3, FALSE}, /* 1 / 7 */ 71 {0x8000000000000000ULL, FPU_REAL10_BIAS - 3, FALSE}, /* 1 / 8 */ 72 {0xE38E38E38E38E38EULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 9 */ 73 {0xCCCCCCCCCCCCCCCDULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 10 */ 74 {0xBA2E8BA2E8BA2E8CULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 11 */ 75 {0xAAAAAAAAAAAAAAABULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 12 */ 76 {0x9D89D89D89D89D8AULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 13 */ 77 {0x9249249249249249ULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 14 */ 78 {0x8888888888888889ULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 15 */ 79 {0x8000000000000000ULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 16 */ 80 {0xF0F0F0F0F0F0F0F0ULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 17 */ 81 {0xE38E38E38E38E38EULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 18 */ 82 {0xD79435E50D79435EULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 19 */ 83 {0xCCCCCCCCCCCCCCCDULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 20 */ 84 {0xC30C30C30C30C30CULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 21 */ 85 {0xBA2E8BA2E8BA2E8BULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 22 */ 86 {0xB21642C8590B2164ULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 23 */ 87 {0xAAAAAAAAAAAAAAABULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 24 */ 88 {0xA3D70A3D70A3D70AULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 25 */ 89 {0x9D89D89D89D89D8AULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 26 */ 90 {0x97B425ED097B425FULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 27 */ 91 {0x9249249249249249ULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 28 */ 92 {0x8D3DCB08D3DCB08DULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 29 */ 93 {0x8888888888888889ULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 30 */ 94 {0x8421084210842108ULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 31 */ 95 {0x8000000000000000ULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 32 */ 96 {0xF83E0F83E0F83E0FULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 33 */ 97 {0xF0F0F0F0F0F0F0F0ULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 34 */ 98 {0xEA0EA0EA0EA0EA0EULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 35 */ 99 {0xE38E38E38E38E38EULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 36 */ 100 {0xDD67C8A60DD67C8AULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 37 */ 101 {0xD79435E50D79435EULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 38 */ 102 {0xD20D20D20D20D20DULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 39 */ 103 {0xCCCCCCCCCCCCCCCDULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 40 */ 104 {0xC7CE0C7CE0C7CE0CULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 41 */ 105 {0xC30C30C30C30C30CULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 42 */ 106 {0xBE82FA0BE82FA0BFULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 43 */ 107 {0xBA2E8BA2E8BA2E8BULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 44 */ 108 {0xB60B60B60B60B60BULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 45 */ 109 {0xB21642C8590B2164ULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 46 */ 110 {0xAE4C415C9882B931ULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 47 */ 111 {0xAAAAAAAAAAAAAAABULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 48 */ 112 {0xA72F05397829CBC1ULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 49 */ 113 {0xA3D70A3D70A3D70AULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 50 */ 114 }; 115 116 static const FAST486_FPU_DATA_REG FpuInverseNumberSine[INVERSE_NUMBERS_COUNT] = 117 { 118 {0xAAAAAAAAAAAAAAAAULL, FPU_REAL10_BIAS - 3, FALSE}, /* 1 / 6 */ 119 {0xCCCCCCCCCCCCCCCCULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 20 */ 120 {0xC30C30C30C30C30CULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 42 */ 121 {0xE38E38E38E38E38EULL, FPU_REAL10_BIAS - 7, FALSE}, /* 1 / 72 */ 122 {0x94F2094F2094F209ULL, FPU_REAL10_BIAS - 7, FALSE}, /* 1 / 110 */ 123 {0xD20D20D20D20D20DULL, FPU_REAL10_BIAS - 8, FALSE}, /* 1 / 156 */ 124 {0x9C09C09C09C09C09ULL, FPU_REAL10_BIAS - 8, FALSE}, /* 1 / 210 */ 125 {0xF0F0F0F0F0F0F0F0ULL, FPU_REAL10_BIAS - 9, FALSE}, /* 1 / 272 */ 126 {0xBFA02FE80BFA02FEULL, FPU_REAL10_BIAS - 9, FALSE}, /* 1 / 342 */ 127 {0x9C09C09C09C09C09ULL, FPU_REAL10_BIAS - 9, FALSE}, /* 1 / 420 */ 128 {0x81848DA8FAF0D277ULL, FPU_REAL10_BIAS - 9, FALSE}, /* 1 / 506 */ 129 {0xDA740DA740DA740DULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 600 */ 130 {0xBAB656100BAB6561ULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 702 */ 131 {0xA16B312EA8FC377CULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 812 */ 132 {0x8CF008CF008CF008ULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 930 */ 133 {0xF83E0F83E0F83E0FULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1056 */ 134 {0xDC4A00DC4A00DC4AULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1190 */ 135 {0xC4CE07B00C4CE07BULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1332 */ 136 {0xB0E2A2600B0E2A26ULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1482 */ 137 {0x9FD809FD809FD809ULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1640 */ 138 {0x9126D6E4802449B5ULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1806 */ 139 {0x84655D9BAB2F1008ULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1980 */ 140 {0xF2805AF0221A0CC9ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2162 */ 141 {0xDEE95C4CA037BA57ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2352 */ 142 {0xCD9A673400CD9A67ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2550 */ 143 {0xBE3C310B84A4F832ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2756 */ 144 {0xB087277A39941560ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2970 */ 145 {0xA44029100A440291ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 3192 */ 146 {0x9936034AA9121AA1ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 3422 */ 147 {0x8F3F82A86DACA008ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 3660 */ 148 {0x8639F00218E7C008ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 3906 */ 149 {0xFC0FC0FC0FC0FC0FULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 4160 */ 150 {0xED208916CF412FD1ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 4422 */ 151 {0xDF7B4EC93886702DULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 4692 */ 152 {0xD2FB287C7224E167ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 4970 */ 153 {0xC78031E00C78031EULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 5256 */ 154 {0xBCEEBFB33F021F2EULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 5550 */ 155 {0xB32EB86E96D5D441ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 5852 */ 156 {0xAA2B0A62E08248F3ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 6162 */ 157 {0xA1D139855F7268EDULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 6480 */ 158 {0x9A1100604AA03C2EULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 6806 */ 159 {0x92DC0092DC0092DCULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 7140 */ 160 {0x8C258008C258008CULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 7482 */ 161 {0x85E230A32BAB46DDULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 7832 */ 162 {0x8008008008008008ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 8190 */ 163 {0xF51BE2CC2D7AAC94ULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 8556 */ 164 {0xEAD7EC46DDA80C62ULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 8930 */ 165 {0xE135A9C97500E135ULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 9312 */ 166 {0xD8281B71177BDB7BULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 9702 */ 167 {0xCFA3892CE9FFCC17ULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 10100 */ 168 }; 169 170 static const FAST486_FPU_DATA_REG FpuInverseNumberCosine[INVERSE_NUMBERS_COUNT] = 171 { 172 {0x8000000000000000ULL, FPU_REAL10_BIAS - 1, FALSE}, /* 1 / 2 */ 173 {0xAAAAAAAAAAAAAAAAULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 12 */ 174 {0x8888888888888888ULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 30 */ 175 {0x9249249249249249ULL, FPU_REAL10_BIAS - 6, FALSE}, /* 1 / 56 */ 176 {0xB60B60B60B60B60BULL, FPU_REAL10_BIAS - 7, FALSE}, /* 1 / 90 */ 177 {0xF83E0F83E0F83E0FULL, FPU_REAL10_BIAS - 8, FALSE}, /* 1 / 132 */ 178 {0xB40B40B40B40B40BULL, FPU_REAL10_BIAS - 8, FALSE}, /* 1 / 182 */ 179 {0x8888888888888888ULL, FPU_REAL10_BIAS - 8, FALSE}, /* 1 / 240 */ 180 {0xD62B80D62B80D62BULL, FPU_REAL10_BIAS - 9, FALSE}, /* 1 / 306 */ 181 {0xAC7691840AC76918ULL, FPU_REAL10_BIAS - 9, FALSE}, /* 1 / 380 */ 182 {0x8DDA520237694808ULL, FPU_REAL10_BIAS - 9, FALSE}, /* 1 / 462 */ 183 {0xED7303B5CC0ED730ULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 552 */ 184 {0xC9A633FCD967300CULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 650 */ 185 {0xAD602B580AD602B5ULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 756 */ 186 {0x96A850096A850096ULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 870 */ 187 {0x8421084210842108ULL, FPU_REAL10_BIAS - 10, FALSE}, /* 1 / 992 */ 188 {0xE9A3D25E00E9A3D2ULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1122 */ 189 {0xD00D00D00D00D00DULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1260 */ 190 {0xBA7258200BA72582ULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1406 */ 191 {0xA80A80A80A80A80AULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1560 */ 192 {0x983B773A92E16009ULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1722 */ 193 {0x8A8DCD1FEEAE465CULL, FPU_REAL10_BIAS - 11, FALSE}, /* 1 / 1892 */ 194 {0xFD477B6C956529CDULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2070 */ 195 {0xE865AC7B7603A196ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2256 */ 196 {0xD5FEBF01E17D2DC4ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2450 */ 197 {0xC5B200C5B200C5B2ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2652 */ 198 {0xB7307B1492B1D28FULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 2862 */ 199 {0xAA392F35DC17F00AULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 3080 */ 200 {0x9E96394D47B46C68ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 3306 */ 201 {0x941A9CC82BF7E68BULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 3540 */ 202 {0x8AA08EF5936D4008ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 3782 */ 203 {0x8208208208208208ULL, FPU_REAL10_BIAS - 12, FALSE}, /* 1 / 4032 */ 204 {0xF46C5E0BB22F800FULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 4290 */ 205 {0xE6271BA5329217D3ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 4556 */ 206 {0xD918B2EF5B7B4866ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 4830 */ 207 {0xCD1ED923A7DCBEB2ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 5112 */ 208 {0xC21BDD800C21BDD8ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 5402 */ 209 {0xB7F5F08CD84C2BD5ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 5700 */ 210 {0xAE968C517F46800AULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 6006 */ 211 {0xA5E9F6ED347F0721ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 6320 */ 212 {0x9DDEDA75A1CD4726ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 6642 */ 213 {0x9665EE14DB2283E4ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 6972 */ 214 {0x8F71AD362448008FULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 7310 */ 215 {0x88F61A371B048C2BULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 7656 */ 216 {0x82E88A942AB2D933ULL, FPU_REAL10_BIAS - 13, FALSE}, /* 1 / 8010 */ 217 {0xFA7EF5D91AC9538AULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 8372 */ 218 {0xEFE4D31416B96CFEULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 8742 */ 219 {0xE5F36CB00E5F36CBULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 9120 */ 220 {0xDC9D0ECFCB6E9378ULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 9506 */ 221 {0xD3D56292AB7E800DULL, FPU_REAL10_BIAS - 14, FALSE}, /* 1 / 9900 */ 222 }; 223 224 static const FAST486_FPU_DATA_REG FpuInverseNumberAtan[INVERSE_NUMBERS_COUNT] = 225 { 226 {0xAAAAAAAAAAAAAAAAULL, FPU_REAL10_BIAS - 1, FALSE}, /* 2 / 3 */ 227 {0xCCCCCCCCCCCCCCCCULL, FPU_REAL10_BIAS - 1, FALSE}, /* 4 / 5 */ 228 {0xDB6DB6DB6DB6DB6DULL, FPU_REAL10_BIAS - 1, FALSE}, /* 6 / 7 */ 229 {0xE38E38E38E38E38EULL, FPU_REAL10_BIAS - 1, FALSE}, /* 8 / 9 */ 230 {0xE8BA2E8BA2E8BA2EULL, FPU_REAL10_BIAS - 1, FALSE}, /* 10 / 11 */ 231 {0xEC4EC4EC4EC4EC4EULL, FPU_REAL10_BIAS - 1, FALSE}, /* 12 / 13 */ 232 {0xEEEEEEEEEEEEEEEEULL, FPU_REAL10_BIAS - 1, FALSE}, /* 14 / 15 */ 233 {0xF0F0F0F0F0F0F0F0ULL, FPU_REAL10_BIAS - 1, FALSE}, /* 16 / 17 */ 234 {0xF286BCA1AF286BCAULL, FPU_REAL10_BIAS - 1, FALSE}, /* 18 / 19 */ 235 {0xF3CF3CF3CF3CF3CFULL, FPU_REAL10_BIAS - 1, FALSE}, /* 20 / 21 */ 236 {0xF4DE9BD37A6F4DE9ULL, FPU_REAL10_BIAS - 1, FALSE}, /* 22 / 23 */ 237 {0xF5C28F5C28F5C28FULL, FPU_REAL10_BIAS - 1, FALSE}, /* 24 / 25 */ 238 {0xF684BDA12F684BDAULL, FPU_REAL10_BIAS - 1, FALSE}, /* 26 / 27 */ 239 {0xF72C234F72C234F7ULL, FPU_REAL10_BIAS - 1, FALSE}, /* 28 / 29 */ 240 {0xF7BDEF7BDEF7BDEFULL, FPU_REAL10_BIAS - 1, FALSE}, /* 30 / 31 */ 241 {0xF83E0F83E0F83E0FULL, FPU_REAL10_BIAS - 1, FALSE}, /* 32 / 33 */ 242 {0xF8AF8AF8AF8AF8AFULL, FPU_REAL10_BIAS - 1, FALSE}, /* 34 / 35 */ 243 {0xF914C1BACF914C1BULL, FPU_REAL10_BIAS - 1, FALSE}, /* 36 / 37 */ 244 {0xF96F96F96F96F96FULL, FPU_REAL10_BIAS - 1, FALSE}, /* 38 / 39 */ 245 {0xF9C18F9C18F9C18FULL, FPU_REAL10_BIAS - 1, FALSE}, /* 40 / 41 */ 246 {0xFA0BE82FA0BE82FAULL, FPU_REAL10_BIAS - 1, FALSE}, /* 42 / 43 */ 247 {0xFA4FA4FA4FA4FA4FULL, FPU_REAL10_BIAS - 1, FALSE}, /* 44 / 45 */ 248 {0xFA8D9DF51B3BEA36ULL, FPU_REAL10_BIAS - 1, FALSE}, /* 46 / 47 */ 249 {0xFAC687D6343EB1A1ULL, FPU_REAL10_BIAS - 1, FALSE}, /* 48 / 49 */ 250 {0xFAFAFAFAFAFAFAFAULL, FPU_REAL10_BIAS - 1, FALSE}, /* 50 / 51 */ 251 {0xFB2B78C13521CFB2ULL, FPU_REAL10_BIAS - 1, FALSE}, /* 52 / 53 */ 252 {0xFB586FB586FB586FULL, FPU_REAL10_BIAS - 1, FALSE}, /* 54 / 55 */ 253 {0xFB823EE08FB823EEULL, FPU_REAL10_BIAS - 1, FALSE}, /* 56 / 57 */ 254 {0xFBA9386822B63CBEULL, FPU_REAL10_BIAS - 1, FALSE}, /* 58 / 59 */ 255 {0xFBCDA3AC10C9714FULL, FPU_REAL10_BIAS - 1, FALSE}, /* 60 / 61 */ 256 {0xFBEFBEFBEFBEFBEFULL, FPU_REAL10_BIAS - 1, FALSE}, /* 62 / 63 */ 257 {0xFC0FC0FC0FC0FC0FULL, FPU_REAL10_BIAS - 1, FALSE}, /* 64 / 65 */ 258 {0xFC2DD9CA81E9131AULL, FPU_REAL10_BIAS - 1, FALSE}, /* 66 / 67 */ 259 {0xFC4A33F128CFC4A3ULL, FPU_REAL10_BIAS - 1, FALSE}, /* 68 / 69 */ 260 {0xFC64F52EDF8C9EA5ULL, FPU_REAL10_BIAS - 1, FALSE}, /* 70 / 71 */ 261 {0xFC7E3F1F8FC7E3F1ULL, FPU_REAL10_BIAS - 1, FALSE}, /* 72 / 73 */ 262 {0xFC962FC962FC962FULL, FPU_REAL10_BIAS - 1, FALSE}, /* 74 / 75 */ 263 {0xFCACE213F2B3884FULL, FPU_REAL10_BIAS - 1, FALSE}, /* 76 / 77 */ 264 {0xFCC26E2D5DF984DCULL, FPU_REAL10_BIAS - 1, FALSE}, /* 78 / 79 */ 265 {0xFCD6E9E06522C3F3ULL, FPU_REAL10_BIAS - 1, FALSE}, /* 80 / 81 */ 266 {0xFCEA68DE12818ACBULL, FPU_REAL10_BIAS - 1, FALSE}, /* 82 / 83 */ 267 {0xFCFCFCFCFCFCFCFCULL, FPU_REAL10_BIAS - 1, FALSE}, /* 84 / 85 */ 268 {0xFD0EB66FD0EB66FDULL, FPU_REAL10_BIAS - 1, FALSE}, /* 86 / 87 */ 269 {0xFD1FA3F47E8FD1FAULL, FPU_REAL10_BIAS - 1, FALSE}, /* 88 / 89 */ 270 {0xFD2FD2FD2FD2FD2FULL, FPU_REAL10_BIAS - 1, FALSE}, /* 90 / 91 */ 271 {0xFD3F4FD3F4FD3F4FULL, FPU_REAL10_BIAS - 1, FALSE}, /* 92 / 93 */ 272 {0xFD4E25B9EFD4E25BULL, FPU_REAL10_BIAS - 1, FALSE}, /* 94 / 95 */ 273 {0xFD5C5F02A3A0FD5CULL, FPU_REAL10_BIAS - 1, FALSE}, /* 96 / 97 */ 274 {0xFD6A052BF5A814AFULL, FPU_REAL10_BIAS - 1, FALSE}, /* 98 / 99 */ 275 {0xFD7720F353A4C0A2ULL, FPU_REAL10_BIAS - 1, FALSE}, /* 100 / 101 */ 276 }; 277 278 /* PRIVATE FUNCTIONS **********************************************************/ 279 280 #ifndef FAST486_NO_FPU 281 282 static ULONGLONG 283 UnsignedMult128(ULONGLONG Multiplicand, 284 ULONGLONG Multiplier, 285 ULONGLONG *HighProduct) 286 { 287 ULONG MultiplicandLow, MultiplicandHigh, MultiplierLow, MultiplierHigh; 288 ULONG IntermediateLow, IntermediateHigh; 289 ULONGLONG LowProduct, Intermediate, Intermediate1, Intermediate2; 290 291 MultiplicandLow = (ULONG)(Multiplicand & 0xFFFFFFFFULL); 292 MultiplicandHigh = (ULONG)(Multiplicand >> 32); 293 MultiplierLow = (ULONG)(Multiplier & 0xFFFFFFFFULL); 294 MultiplierHigh = (ULONG)(Multiplier >> 32); 295 296 LowProduct = (ULONGLONG)MultiplicandLow * (ULONGLONG)MultiplierLow; 297 Intermediate1 = (ULONGLONG)MultiplicandLow * (ULONGLONG)MultiplierHigh; 298 Intermediate2 = (ULONGLONG)MultiplicandHigh * (ULONGLONG)MultiplierLow; 299 *HighProduct = (ULONGLONG)MultiplicandHigh * (ULONGLONG)MultiplierHigh; 300 301 Intermediate = Intermediate1 + Intermediate2; 302 if (Intermediate < Intermediate1) *HighProduct += 1ULL << 32; 303 304 IntermediateLow = (ULONG)(Intermediate & 0xFFFFFFFFULL); 305 IntermediateHigh = (ULONG)(Intermediate >> 32); 306 307 LowProduct += (ULONGLONG)IntermediateLow << 32; 308 if ((ULONG)(LowProduct >> 32) < IntermediateLow) (*HighProduct)++; 309 310 *HighProduct += IntermediateHigh; 311 return LowProduct; 312 } 313 314 static ULONGLONG 315 UnsignedDivMod128(ULONGLONG DividendLow, 316 ULONGLONG DividendHigh, 317 ULONGLONG Divisor, 318 PULONGLONG QuotientLow, 319 PULONGLONG QuotientHigh) 320 { 321 ULONGLONG ValueLow = DividendLow; 322 ULONGLONG ValueHigh = DividendHigh; 323 ULONGLONG CurrentLow = 0ULL; 324 ULONGLONG CurrentHigh = Divisor; 325 ULONG Bits; 326 327 ASSERT(Divisor != 0ULL); 328 329 /* Initialize the quotient */ 330 *QuotientLow = *QuotientHigh = 0ULL; 331 332 /* Exit early if the dividend is lower than the divisor */ 333 if ((DividendHigh == 0ULL) && (DividendLow < Divisor)) return ValueLow; 334 335 /* Normalize the current divisor */ 336 Bits = CountLeadingZeros64(CurrentHigh); 337 CurrentHigh <<= Bits; 338 339 while (TRUE) 340 { 341 /* Shift the quotient left by one bit */ 342 *QuotientHigh <<= 1; 343 *QuotientHigh |= *QuotientLow >> 63; 344 *QuotientLow <<= 1; 345 346 /* Check if the value is higher than or equal to the current divisor */ 347 if ((ValueHigh > CurrentHigh) 348 || ((ValueHigh == CurrentHigh) && (ValueLow >= CurrentLow))) 349 { 350 BOOLEAN Carry = ValueLow < CurrentLow; 351 352 /* Subtract the current divisor from the value */ 353 ValueHigh -= CurrentHigh; 354 ValueLow -= CurrentLow; 355 if (Carry) ValueHigh--; 356 357 /* Set the lowest bit of the quotient */ 358 *QuotientLow |= 1; 359 360 /* Stop if the value is lower than the original divisor */ 361 if ((ValueHigh == 0ULL) && (ValueLow < Divisor)) break; 362 } 363 364 /* Shift the current divisor right by one bit */ 365 CurrentLow >>= 1; 366 CurrentLow |= (CurrentHigh & 1) << 63; 367 CurrentHigh >>= 1; 368 } 369 370 /* 371 * Calculate the number of significant bits the current 372 * divisor has more than the original divisor 373 */ 374 Bits = CountLeadingZeros64(Divisor); 375 if (CurrentHigh > 0ULL) Bits += 64 - CountLeadingZeros64(CurrentHigh); 376 else Bits -= CountLeadingZeros64(CurrentLow); 377 378 if (Bits >= 64) 379 { 380 *QuotientHigh = *QuotientLow; 381 *QuotientLow = 0ULL; 382 Bits -= 64; 383 } 384 385 if (Bits) 386 { 387 /* Shift the quotient left by that amount */ 388 *QuotientHigh <<= Bits; 389 *QuotientHigh |= *QuotientLow >> (64 - Bits); 390 *QuotientLow <<= Bits; 391 } 392 393 /* Return the remainder */ 394 return ValueLow; 395 } 396 397 static inline VOID FASTCALL 398 Fast486FpuRound(PFAST486_STATE State, 399 PULONGLONG Result, 400 BOOLEAN Sign, 401 ULONGLONG Remainder, 402 INT RemainderHighBit) 403 { 404 switch (State->FpuControl.Rc) 405 { 406 case FPU_ROUND_NEAREST: 407 { 408 /* Check if the highest bit of the remainder is set */ 409 if (Remainder & (1ULL << RemainderHighBit)) 410 { 411 (*Result)++; 412 413 /* Check if all the other bits are clear */ 414 if (!(Remainder & ((1ULL << RemainderHighBit) - 1ULL))) 415 { 416 /* Round to even */ 417 *Result &= ~1ULL; 418 } 419 } 420 421 break; 422 } 423 424 case FPU_ROUND_DOWN: 425 { 426 if ((Remainder != 0ULL) && Sign) (*Result)++; 427 break; 428 } 429 430 case FPU_ROUND_UP: 431 { 432 if ((Remainder != 0ULL) && !Sign) (*Result)++; 433 break; 434 } 435 436 default: 437 { 438 /* Leave it truncated */ 439 } 440 } 441 } 442 443 static inline VOID FASTCALL 444 Fast486FpuFromInteger(PFAST486_STATE State, 445 LONGLONG Value, 446 PFAST486_FPU_DATA_REG Result) 447 { 448 ULONG ZeroCount; 449 450 Result->Sign = Result->Exponent = Result->Mantissa = 0; 451 if (Value == 0LL) return; 452 453 if (Value < 0LL) 454 { 455 Result->Sign = TRUE; 456 Value = -Value; 457 } 458 459 Result->Mantissa = (ULONGLONG)Value; 460 ZeroCount = CountLeadingZeros64(Result->Mantissa); 461 462 Result->Mantissa <<= ZeroCount; 463 Result->Exponent = FPU_REAL10_BIAS + 63 - ZeroCount; 464 } 465 466 static inline BOOLEAN FASTCALL 467 Fast486FpuToInteger(PFAST486_STATE State, 468 PCFAST486_FPU_DATA_REG Value, 469 PLONGLONG Result) 470 { 471 ULONG Bits; 472 ULONGLONG Remainder; 473 SHORT UnbiasedExp = (SHORT)Value->Exponent - FPU_REAL10_BIAS; 474 475 if (FPU_IS_ZERO(Value)) 476 { 477 *Result = 0LL; 478 return TRUE; 479 } 480 481 if (FPU_IS_NAN(Value) || !FPU_IS_NORMALIZED(Value) || (UnbiasedExp >= 63)) 482 { 483 /* Raise an invalid operation exception */ 484 State->FpuStatus.Ie = TRUE; 485 486 if (State->FpuControl.Im) 487 { 488 *Result = 0x8000000000000000LL; 489 return TRUE; 490 } 491 else 492 { 493 return FALSE; 494 } 495 } 496 497 if (UnbiasedExp >= 0) 498 { 499 Bits = 63 - UnbiasedExp; 500 501 /* Calculate the result and the remainder */ 502 *Result = (LONGLONG)(Value->Mantissa >> Bits); 503 Remainder = Value->Mantissa & ((1ULL << Bits) - 1); 504 } 505 else 506 { 507 /* The result is zero */ 508 *Result = 0LL; 509 Bits = 64; 510 511 if (UnbiasedExp >= -64) 512 { 513 Remainder = Value->Mantissa >> (-1 - UnbiasedExp); 514 } 515 else 516 { 517 /* Too small to even have a remainder */ 518 Remainder = 0ULL; 519 } 520 } 521 522 /* The result must be positive here */ 523 ASSERT(*Result >= 0LL); 524 525 /* Perform rounding */ 526 Fast486FpuRound(State, (PULONGLONG)Result, Value->Sign, Remainder, Bits - 1); 527 528 if (Value->Sign) *Result = -*Result; 529 return TRUE; 530 } 531 532 static inline VOID FASTCALL 533 Fast486FpuFromSingleReal(PFAST486_STATE State, 534 ULONG Value, 535 PFAST486_FPU_DATA_REG Result) 536 { 537 /* Extract the sign, exponent and mantissa */ 538 Result->Sign = (UCHAR)(Value >> 31); 539 Result->Exponent = (USHORT)((Value >> 23) & 0xFF); 540 Result->Mantissa = (((ULONGLONG)Value & 0x7FFFFFULL) | 0x800000ULL) << 40; 541 542 /* If this is a zero, we're done */ 543 if (Value == 0) return; 544 545 if (Result->Exponent == 0xFF) Result->Exponent = FPU_MAX_EXPONENT + 1; 546 else 547 { 548 /* Adjust the exponent bias */ 549 Result->Exponent += (FPU_REAL10_BIAS - FPU_REAL4_BIAS); 550 } 551 } 552 553 static inline BOOLEAN FASTCALL 554 Fast486FpuToSingleReal(PFAST486_STATE State, 555 PCFAST486_FPU_DATA_REG Value, 556 PULONG Result) 557 { 558 ULONGLONG Remainder; 559 SHORT UnbiasedExp = (SHORT)Value->Exponent - FPU_REAL10_BIAS; 560 ULONGLONG Result64; 561 562 if (FPU_IS_ZERO(Value)) 563 { 564 *Result = 0; 565 return TRUE; 566 } 567 568 /* Calculate the mantissa */ 569 *Result = (ULONG)(Value->Mantissa >> 40) & 0x7FFFFF; 570 571 if (FPU_IS_NAN(Value)) 572 { 573 *Result |= FPU_REAL4_INFINITY; 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 */ 604 *Result = FPU_REAL4_INFINITY; 605 goto SetSign; 606 } 607 else 608 { 609 return FALSE; 610 } 611 } 612 613 /* Calculate the remainder */ 614 Remainder = Value->Mantissa & ((1ULL << 40) - 1); 615 616 /* Store the biased exponent */ 617 *Result |= (ULONG)(UnbiasedExp + FPU_REAL4_BIAS) << 23; 618 619 /* Perform rounding */ 620 Result64 = (ULONGLONG)*Result; 621 Fast486FpuRound(State, &Result64, Value->Sign, Remainder, 39); 622 *Result = (ULONG)Result64; 623 624 SetSign: 625 626 if (Value->Sign) *Result |= 0x80000000; 627 return TRUE; 628 } 629 630 static inline VOID FASTCALL 631 Fast486FpuFromDoubleReal(PFAST486_STATE State, 632 ULONGLONG Value, 633 PFAST486_FPU_DATA_REG Result) 634 { 635 /* Extract the sign, exponent and mantissa */ 636 Result->Sign = (UCHAR)(Value >> 63); 637 Result->Exponent = (USHORT)((Value >> 52) & 0x7FF); 638 Result->Mantissa = (((ULONGLONG)Value & 0xFFFFFFFFFFFFFULL) | 0x10000000000000ULL) << 11; 639 640 /* If this is a zero, we're done */ 641 if (Value == 0) return; 642 643 if (Result->Exponent == 0x7FF) Result->Exponent = FPU_MAX_EXPONENT + 1; 644 else 645 { 646 /* Adjust the exponent bias */ 647 Result->Exponent += (FPU_REAL10_BIAS - FPU_REAL8_BIAS); 648 } 649 } 650 651 static inline BOOLEAN FASTCALL 652 Fast486FpuToDoubleReal(PFAST486_STATE State, 653 PCFAST486_FPU_DATA_REG Value, 654 PULONGLONG Result) 655 { 656 ULONGLONG Remainder; 657 SHORT UnbiasedExp = (SHORT)Value->Exponent - FPU_REAL10_BIAS; 658 659 if (FPU_IS_ZERO(Value)) 660 { 661 *Result = 0LL; 662 return TRUE; 663 } 664 665 /* Calculate the mantissa */ 666 *Result = (Value->Mantissa >> 11) & ((1ULL << 52) - 1); 667 668 if (FPU_IS_NAN(Value)) 669 { 670 *Result |= FPU_REAL8_INFINITY; 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 */ 701 *Result = FPU_REAL8_INFINITY; 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 */ 717 Fast486FpuRound(State, Result, Value->Sign, Remainder, 10); 718 719 SetSign: 720 721 if (Value->Sign) *Result |= 1ULL << 63; 722 return TRUE; 723 } 724 725 static inline VOID FASTCALL 726 Fast486FpuFromPackedBcd(PFAST486_STATE State, 727 PUCHAR Value, 728 PFAST486_FPU_DATA_REG Result) 729 { 730 INT i; 731 LONGLONG IntVal = 0LL; 732 733 for (i = 8; i >= 0; i--) 734 { 735 IntVal *= 100LL; 736 IntVal += (Value[i] >> 4) * 10 + (Value[i] & 0x0F); 737 } 738 739 /* Apply the sign */ 740 if (Value[9] & 0x80) IntVal = -IntVal; 741 742 /* Now convert the integer to FP80 */ 743 Fast486FpuFromInteger(State, IntVal, Result); 744 } 745 746 static inline BOOLEAN FASTCALL 747 Fast486FpuToPackedBcd(PFAST486_STATE State, 748 PCFAST486_FPU_DATA_REG Value, 749 PUCHAR Result) 750 { 751 INT i; 752 LONGLONG IntVal; 753 754 /* Convert it to an integer first */ 755 if (!Fast486FpuToInteger(State, Value, &IntVal)) return FALSE; 756 757 if (IntVal < 0LL) 758 { 759 IntVal = -IntVal; 760 Result[9] = 0x80; 761 } 762 763 for (i = 0; i < 9; i++) 764 { 765 Result[i] = (UCHAR)((IntVal % 10) + (((IntVal / 10) % 10) << 4)); 766 IntVal /= 100LL; 767 } 768 769 return TRUE; 770 } 771 772 static inline BOOLEAN FASTCALL 773 Fast486FpuAdd(PFAST486_STATE State, 774 PCFAST486_FPU_DATA_REG FirstOperand, 775 PCFAST486_FPU_DATA_REG SecondOperand, 776 PFAST486_FPU_DATA_REG Result) 777 { 778 FAST486_FPU_DATA_REG FirstAdjusted = *FirstOperand; 779 FAST486_FPU_DATA_REG SecondAdjusted = *SecondOperand; 780 FAST486_FPU_DATA_REG TempResult; 781 782 if (FPU_IS_INDEFINITE(FirstOperand) 783 || FPU_IS_INDEFINITE(SecondOperand) 784 || (FPU_IS_POS_INF(FirstOperand) && FPU_IS_NEG_INF(SecondOperand)) 785 || (FPU_IS_NEG_INF(FirstOperand) && FPU_IS_POS_INF(SecondOperand))) 786 { 787 /* The result will be indefinite */ 788 Result->Sign = TRUE; 789 Result->Exponent = FPU_MAX_EXPONENT + 1; 790 Result->Mantissa = FPU_INDEFINITE_MANTISSA; 791 return TRUE; 792 } 793 794 if ((!FPU_IS_NORMALIZED(FirstOperand) || !FPU_IS_NORMALIZED(SecondOperand))) 795 { 796 /* Raise the denormalized exception */ 797 State->FpuStatus.De = TRUE; 798 799 if (!State->FpuControl.Dm) 800 { 801 return FALSE; 802 } 803 } 804 805 if (FPU_IS_ZERO(FirstOperand) || FPU_IS_INFINITY(SecondOperand)) 806 { 807 /* The second operand is the result */ 808 *Result = *SecondOperand; 809 return TRUE; 810 } 811 812 if (FPU_IS_ZERO(SecondOperand) || FPU_IS_INFINITY(FirstOperand)) 813 { 814 /* The first operand is the result */ 815 *Result = *FirstOperand; 816 return TRUE; 817 } 818 819 /* Find the largest exponent */ 820 TempResult.Exponent = max(FirstOperand->Exponent, SecondOperand->Exponent); 821 822 /* Adjust the first operand to it... */ 823 if (FirstAdjusted.Exponent < TempResult.Exponent) 824 { 825 if ((TempResult.Exponent - FirstAdjusted.Exponent) < 64) 826 { 827 FirstAdjusted.Mantissa >>= (TempResult.Exponent - FirstAdjusted.Exponent); 828 FirstAdjusted.Exponent = TempResult.Exponent; 829 } 830 else 831 { 832 /* The second operand is the result */ 833 *Result = *SecondOperand; 834 return TRUE; 835 } 836 } 837 838 /* ... and the second one too */ 839 if (SecondAdjusted.Exponent < TempResult.Exponent) 840 { 841 if ((TempResult.Exponent - SecondAdjusted.Exponent) < 64) 842 { 843 SecondAdjusted.Mantissa >>= (TempResult.Exponent - SecondAdjusted.Exponent); 844 SecondAdjusted.Exponent = TempResult.Exponent; 845 } 846 else 847 { 848 /* The first operand is the result */ 849 *Result = *FirstOperand; 850 return TRUE; 851 } 852 } 853 854 if (FirstAdjusted.Sign == SecondAdjusted.Sign) 855 { 856 /* Calculate the mantissa and sign of the result */ 857 TempResult.Mantissa = FirstAdjusted.Mantissa + SecondAdjusted.Mantissa; 858 TempResult.Sign = FirstAdjusted.Sign; 859 } 860 else 861 { 862 /* Calculate the sign of the result */ 863 if (FirstAdjusted.Mantissa > SecondAdjusted.Mantissa) TempResult.Sign = FirstAdjusted.Sign; 864 else if (FirstAdjusted.Mantissa < SecondAdjusted.Mantissa) TempResult.Sign = SecondAdjusted.Sign; 865 else TempResult.Sign = FALSE; 866 867 /* Invert the negative mantissa */ 868 if (FirstAdjusted.Sign) FirstAdjusted.Mantissa = -(LONGLONG)FirstAdjusted.Mantissa; 869 if (SecondAdjusted.Sign) SecondAdjusted.Mantissa = -(LONGLONG)SecondAdjusted.Mantissa; 870 871 /* Calculate the mantissa of the result */ 872 TempResult.Mantissa = FirstAdjusted.Mantissa + SecondAdjusted.Mantissa; 873 } 874 875 /* Did it overflow? */ 876 if (FirstAdjusted.Sign == SecondAdjusted.Sign) 877 { 878 if (TempResult.Mantissa < FirstAdjusted.Mantissa 879 || TempResult.Mantissa < SecondAdjusted.Mantissa) 880 { 881 if (TempResult.Exponent == FPU_MAX_EXPONENT) 882 { 883 /* Raise the overflow exception */ 884 State->FpuStatus.Oe = TRUE; 885 886 if (State->FpuControl.Om) 887 { 888 /* Total overflow, return infinity */ 889 TempResult.Mantissa = FPU_MANTISSA_HIGH_BIT; 890 TempResult.Exponent = FPU_MAX_EXPONENT + 1; 891 } 892 else 893 { 894 return FALSE; 895 } 896 } 897 else 898 { 899 /* Lose the LSB in favor of the carry */ 900 TempResult.Mantissa >>= 1; 901 TempResult.Mantissa |= FPU_MANTISSA_HIGH_BIT; 902 TempResult.Exponent++; 903 } 904 } 905 } 906 else 907 { 908 if (TempResult.Mantissa >= FirstAdjusted.Mantissa 909 && TempResult.Mantissa >= SecondAdjusted.Mantissa) 910 { 911 /* Reverse the mantissa */ 912 TempResult.Mantissa = -(LONGLONG)TempResult.Mantissa; 913 } 914 } 915 916 /* Normalize the result and return it */ 917 if (!Fast486FpuNormalize(State, &TempResult)) 918 { 919 /* Exception occurred */ 920 return FALSE; 921 } 922 923 *Result = TempResult; 924 return TRUE; 925 } 926 927 static inline BOOLEAN FASTCALL 928 Fast486FpuSubtract(PFAST486_STATE State, 929 PCFAST486_FPU_DATA_REG FirstOperand, 930 PCFAST486_FPU_DATA_REG SecondOperand, 931 PFAST486_FPU_DATA_REG Result) 932 { 933 FAST486_FPU_DATA_REG NegativeSecondOperand = *SecondOperand; 934 935 /* Invert the sign */ 936 NegativeSecondOperand.Sign = !NegativeSecondOperand.Sign; 937 938 /* And perform an addition instead */ 939 return Fast486FpuAdd(State, FirstOperand, &NegativeSecondOperand, Result); 940 } 941 942 static inline VOID FASTCALL 943 Fast486FpuCompare(PFAST486_STATE State, 944 PCFAST486_FPU_DATA_REG FirstOperand, 945 PCFAST486_FPU_DATA_REG SecondOperand) 946 { 947 if (FPU_IS_NAN(FirstOperand) || FPU_IS_NAN(SecondOperand)) 948 { 949 if ((FPU_IS_POS_INF(FirstOperand) 950 && (!FPU_IS_NAN(SecondOperand) || FPU_IS_NEG_INF(SecondOperand))) 951 || (!FPU_IS_NAN(FirstOperand) && FPU_IS_NEG_INF(SecondOperand))) 952 { 953 State->FpuStatus.Code0 = FALSE; 954 State->FpuStatus.Code2 = FALSE; 955 State->FpuStatus.Code3 = FALSE; 956 } 957 else if ((FPU_IS_POS_INF(SecondOperand) 958 && (!FPU_IS_NAN(FirstOperand) || FPU_IS_NEG_INF(FirstOperand))) 959 || (!FPU_IS_NAN(SecondOperand) && FPU_IS_NEG_INF(FirstOperand))) 960 { 961 State->FpuStatus.Code0 = TRUE; 962 State->FpuStatus.Code2 = FALSE; 963 State->FpuStatus.Code3 = FALSE; 964 } 965 else 966 { 967 State->FpuStatus.Code0 = TRUE; 968 State->FpuStatus.Code2 = TRUE; 969 State->FpuStatus.Code3 = TRUE; 970 } 971 } 972 else 973 { 974 FAST486_FPU_DATA_REG TempResult; 975 976 Fast486FpuSubtract(State, FirstOperand, SecondOperand, &TempResult); 977 978 if (FPU_IS_ZERO(&TempResult)) 979 { 980 State->FpuStatus.Code0 = FALSE; 981 State->FpuStatus.Code2 = FALSE; 982 State->FpuStatus.Code3 = TRUE; 983 } 984 else if (TempResult.Sign) 985 { 986 State->FpuStatus.Code0 = TRUE; 987 State->FpuStatus.Code2 = FALSE; 988 State->FpuStatus.Code3 = FALSE; 989 } 990 else 991 { 992 State->FpuStatus.Code0 = FALSE; 993 State->FpuStatus.Code2 = FALSE; 994 State->FpuStatus.Code3 = FALSE; 995 } 996 } 997 } 998 999 static inline BOOLEAN FASTCALL 1000 Fast486FpuMultiply(PFAST486_STATE State, 1001 PCFAST486_FPU_DATA_REG FirstOperand, 1002 PCFAST486_FPU_DATA_REG SecondOperand, 1003 PFAST486_FPU_DATA_REG Result) 1004 { 1005 FAST486_FPU_DATA_REG TempResult; 1006 LONG Exponent; 1007 1008 if (FPU_IS_INDEFINITE(FirstOperand) 1009 || FPU_IS_INDEFINITE(SecondOperand) 1010 || (FPU_IS_ZERO(FirstOperand) && FPU_IS_INFINITY(SecondOperand)) 1011 || (FPU_IS_INFINITY(FirstOperand) && FPU_IS_ZERO(SecondOperand))) 1012 { 1013 /* The result will be indefinite */ 1014 Result->Sign = TRUE; 1015 Result->Exponent = FPU_MAX_EXPONENT + 1; 1016 Result->Mantissa = FPU_INDEFINITE_MANTISSA; 1017 return TRUE; 1018 } 1019 1020 if (FPU_IS_ZERO(FirstOperand) || FPU_IS_ZERO(SecondOperand)) 1021 { 1022 /* The result will be zero */ 1023 Result->Sign = FirstOperand->Sign ^ SecondOperand->Sign; 1024 Result->Exponent = 0; 1025 Result->Mantissa = 0ULL; 1026 return TRUE; 1027 } 1028 1029 if (FPU_IS_INFINITY(FirstOperand) || FPU_IS_INFINITY(SecondOperand)) 1030 { 1031 /* The result will be infinity */ 1032 Result->Sign = FirstOperand->Sign ^ SecondOperand->Sign; 1033 Result->Exponent = FPU_MAX_EXPONENT + 1; 1034 Result->Mantissa = FPU_MANTISSA_HIGH_BIT; 1035 return TRUE; 1036 } 1037 1038 if ((!FPU_IS_NORMALIZED(FirstOperand) || !FPU_IS_NORMALIZED(SecondOperand))) 1039 { 1040 /* Raise the denormalized exception */ 1041 State->FpuStatus.De = TRUE; 1042 1043 if (!State->FpuControl.Dm) 1044 { 1045 return FALSE; 1046 } 1047 } 1048 1049 /* Calculate the sign */ 1050 TempResult.Sign = FirstOperand->Sign ^ SecondOperand->Sign; 1051 1052 /* Calculate the exponent */ 1053 Exponent = (LONG)FirstOperand->Exponent + (LONG)SecondOperand->Exponent - FPU_REAL10_BIAS + 1; 1054 1055 /* Calculate the mantissa */ 1056 UnsignedMult128(FirstOperand->Mantissa, 1057 SecondOperand->Mantissa, 1058 &TempResult.Mantissa); 1059 1060 if (Exponent < 0) 1061 { 1062 /* Raise the underflow exception */ 1063 State->FpuStatus.Ue = TRUE; 1064 1065 if (!State->FpuControl.Um) 1066 { 1067 return FALSE; 1068 } 1069 1070 /* The exponent will be zero */ 1071 TempResult.Exponent = 0; 1072 1073 /* If possible, denormalize the result, otherwise make it zero */ 1074 if (Exponent > -64) TempResult.Mantissa >>= (-Exponent); 1075 else TempResult.Mantissa = 0ULL; 1076 } 1077 else if (Exponent > FPU_MAX_EXPONENT) 1078 { 1079 /* Raise the overflow exception */ 1080 State->FpuStatus.Oe = TRUE; 1081 1082 if (!State->FpuControl.Om) 1083 { 1084 return FALSE; 1085 } 1086 1087 /* Make the result infinity */ 1088 TempResult.Exponent = FPU_MAX_EXPONENT + 1; 1089 TempResult.Mantissa = FPU_MANTISSA_HIGH_BIT; 1090 } 1091 else TempResult.Exponent = (USHORT)Exponent; 1092 1093 /* Normalize the result */ 1094 if (!Fast486FpuNormalize(State, &TempResult)) 1095 { 1096 /* Exception occurred */ 1097 return FALSE; 1098 } 1099 1100 *Result = TempResult; 1101 return TRUE; 1102 } 1103 1104 static inline BOOLEAN FASTCALL 1105 Fast486FpuDivide(PFAST486_STATE State, 1106 PCFAST486_FPU_DATA_REG FirstOperand, 1107 PCFAST486_FPU_DATA_REG SecondOperand, 1108 PFAST486_FPU_DATA_REG Result) 1109 { 1110 FAST486_FPU_DATA_REG TempResult; 1111 ULONGLONG QuotientLow, QuotientHigh, Remainder; 1112 LONG Exponent; 1113 1114 if (FPU_IS_INDEFINITE(FirstOperand) 1115 || FPU_IS_INDEFINITE(SecondOperand) 1116 || (FPU_IS_INFINITY(FirstOperand) && FPU_IS_INFINITY(SecondOperand)) 1117 || (FPU_IS_ZERO(FirstOperand) && FPU_IS_ZERO(SecondOperand))) 1118 { 1119 /* Raise the invalid operation exception */ 1120 State->FpuStatus.Ie = TRUE; 1121 1122 if (State->FpuControl.Im) 1123 { 1124 /* Return the indefinite NaN */ 1125 Result->Sign = TRUE; 1126 Result->Exponent = FPU_MAX_EXPONENT + 1; 1127 Result->Mantissa = FPU_INDEFINITE_MANTISSA; 1128 return TRUE; 1129 } 1130 else 1131 { 1132 return FALSE; 1133 } 1134 } 1135 1136 if (FPU_IS_ZERO(SecondOperand) || FPU_IS_INFINITY(FirstOperand)) 1137 { 1138 /* Raise the division by zero exception */ 1139 State->FpuStatus.Ze = TRUE; 1140 1141 if (State->FpuControl.Zm) 1142 { 1143 /* Return infinity */ 1144 Result->Sign = FirstOperand->Sign; 1145 Result->Exponent = FPU_MAX_EXPONENT + 1; 1146 Result->Mantissa = FPU_MANTISSA_HIGH_BIT; 1147 return TRUE; 1148 } 1149 else 1150 { 1151 return FALSE; 1152 } 1153 } 1154 1155 /* Calculate the sign of the result */ 1156 TempResult.Sign = FirstOperand->Sign ^ SecondOperand->Sign; 1157 1158 if (FPU_IS_ZERO(FirstOperand) || FPU_IS_INFINITY(SecondOperand)) 1159 { 1160 /* Return zero */ 1161 Result->Sign = TempResult.Sign; 1162 Result->Mantissa = 0ULL; 1163 Result->Exponent = 0; 1164 return TRUE; 1165 } 1166 1167 /* Calculate the exponent of the result */ 1168 Exponent = (LONG)FirstOperand->Exponent - (LONG)SecondOperand->Exponent - 1; 1169 1170 /* Divide the two mantissas */ 1171 Remainder = UnsignedDivMod128(0ULL, 1172 FirstOperand->Mantissa, 1173 SecondOperand->Mantissa, 1174 &QuotientLow, 1175 &QuotientHigh); 1176 UNREFERENCED_PARAMETER(Remainder); // TODO: Rounding 1177 1178 TempResult.Mantissa = QuotientLow; 1179 1180 if (QuotientHigh > 0ULL) 1181 { 1182 ULONG BitsToShift = 64 - CountLeadingZeros64(QuotientHigh); 1183 1184 TempResult.Mantissa >>= BitsToShift; 1185 TempResult.Mantissa |= QuotientHigh << (64 - BitsToShift); 1186 Exponent += BitsToShift; 1187 1188 // TODO: Rounding 1189 } 1190 1191 if (Exponent < -FPU_REAL10_BIAS) 1192 { 1193 TempResult.Mantissa >>= -(Exponent + FPU_REAL10_BIAS); 1194 Exponent = -FPU_REAL10_BIAS; 1195 1196 // TODO: Rounding 1197 } 1198 1199 TempResult.Exponent = (USHORT)(Exponent + FPU_REAL10_BIAS); 1200 1201 /* Normalize the result */ 1202 if (!Fast486FpuNormalize(State, &TempResult)) 1203 { 1204 /* Exception occurred */ 1205 return FALSE; 1206 } 1207 1208 *Result = TempResult; 1209 return TRUE; 1210 } 1211 1212 /* 1213 * Calculates using the identity: 1214 * 2 ^ x - 1 = 1 + sum { 2 * (((x - 1) * ln(2)) ^ n) / n! } 1215 */ 1216 static inline VOID FASTCALL 1217 Fast486FpuCalculateTwoPowerMinusOne(PFAST486_STATE State, 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 */ 1251 if (!Fast486FpuMultiply(State, 1252 &SeriesElement, 1253 &FpuInverseNumber[i - 1], 1254 &SeriesElement)) 1255 { 1256 /* An exception occurred */ 1257 return; 1258 } 1259 } 1260 1261 *Result = TempResult; 1262 } 1263 1264 static inline BOOLEAN FASTCALL 1265 Fast486FpuCalculateLogBase2(PFAST486_STATE State, 1266 PCFAST486_FPU_DATA_REG Operand, 1267 PFAST486_FPU_DATA_REG Result) 1268 { 1269 INT i; 1270 FAST486_FPU_DATA_REG Value = *Operand; 1271 FAST486_FPU_DATA_REG TempResult; 1272 FAST486_FPU_DATA_REG TempValue; 1273 LONGLONG UnbiasedExp = (LONGLONG)Operand->Exponent - FPU_REAL10_BIAS; 1274 1275 if (Operand->Sign) 1276 { 1277 /* Raise the invalid operation exception */ 1278 State->FpuStatus.Ie = TRUE; 1279 1280 if (State->FpuControl.Im) 1281 { 1282 /* Return the indefinite NaN */ 1283 Result->Sign = TRUE; 1284 Result->Exponent = FPU_MAX_EXPONENT + 1; 1285 Result->Mantissa = FPU_INDEFINITE_MANTISSA; 1286 return TRUE; 1287 } 1288 else 1289 { 1290 return FALSE; 1291 } 1292 } 1293 1294 /* Get only the mantissa as a floating-pointer number between 1 and 2 */ 1295 Value.Exponent = FPU_REAL10_BIAS; 1296 1297 /* Check if it's denormalized */ 1298 if (!FPU_IS_NORMALIZED(&Value)) 1299 { 1300 ULONG Bits; 1301 State->FpuStatus.De = TRUE; 1302 1303 if (!State->FpuControl.Dm) 1304 { 1305 return FALSE; 1306 } 1307 1308 /* Normalize the number */ 1309 Bits = CountLeadingZeros64(Value.Mantissa); 1310 UnbiasedExp -= Bits; 1311 Value.Mantissa <<= Bits; 1312 } 1313 1314 TempResult.Sign = FALSE; 1315 TempResult.Exponent = FPU_REAL10_BIAS - 1; 1316 TempResult.Mantissa = 0ULL; 1317 1318 for (i = 63; i >= 0; i--) 1319 { 1320 /* Square the value */ 1321 if (!Fast486FpuMultiply(State, &Value, &Value, &Value)) return FALSE; 1322 1323 /* Subtract two from it */ 1324 if (!Fast486FpuSubtract(State, &Value, &FpuTwo, &TempValue)) return FALSE; 1325 1326 /* Is the result positive? */ 1327 if (!TempValue.Sign) 1328 { 1329 /* Yes, set the appropriate bit in the mantissa */ 1330 TempResult.Mantissa |= 1ULL << i; 1331 1332 /* Halve the value */ 1333 if (!Fast486FpuMultiply(State, &Value, &FpuInverseNumber[1], &Value)) return FALSE; 1334 } 1335 } 1336 1337 /* Normalize the result */ 1338 if (!Fast486FpuNormalize(State, &TempResult)) return FALSE; 1339 1340 /* 1341 * Add the exponent to the result 1342 * log2(x * 2^y) = log2(x) + log2(2^y) = log2(x) + y 1343 */ 1344 Fast486FpuFromInteger(State, UnbiasedExp, &TempValue); 1345 if (!Fast486FpuAdd(State, &TempValue, &TempResult, &TempResult)) return FALSE; 1346 1347 *Result = TempResult; 1348 return TRUE; 1349 } 1350 1351 static inline BOOLEAN FASTCALL 1352 Fast486FpuRemainder(PFAST486_STATE State, 1353 PCFAST486_FPU_DATA_REG FirstOperand, 1354 PCFAST486_FPU_DATA_REG SecondOperand, 1355 BOOLEAN RoundToNearest, 1356 PFAST486_FPU_DATA_REG Result OPTIONAL, 1357 PLONGLONG Quotient OPTIONAL) 1358 { 1359 BOOLEAN Success = FALSE; 1360 INT OldRoundingMode = State->FpuControl.Rc; 1361 LONGLONG Integer; 1362 FAST486_FPU_DATA_REG Temp; 1363 1364 if (!Fast486FpuDivide(State, FirstOperand, SecondOperand, &Temp)) return FALSE; 1365 1366 State->FpuControl.Rc = RoundToNearest ? FPU_ROUND_NEAREST : FPU_ROUND_TRUNCATE; 1367 1368 if (!Fast486FpuToInteger(State, &Temp, &Integer)) goto Cleanup; 1369 1370 if (Result) 1371 { 1372 Fast486FpuFromInteger(State, Integer, &Temp); 1373 if (!Fast486FpuMultiply(State, &Temp, SecondOperand, &Temp)) goto Cleanup; 1374 if (!Fast486FpuSubtract(State, FirstOperand, &Temp, Result)) goto Cleanup; 1375 } 1376 1377 if (Quotient) *Quotient = Integer; 1378 Success = TRUE; 1379 1380 Cleanup: 1381 State->FpuControl.Rc = OldRoundingMode; 1382 return Success; 1383 } 1384 1385 /* 1386 * Calculates using the identity: 1387 * sin(x) = sum { -1^n * x^(2n + 1) / (2n + 1)!, n >= 0 } 1388 */ 1389 static inline BOOLEAN FASTCALL 1390 Fast486FpuCalculateSine(PFAST486_STATE State, 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 1402 if (!Fast486FpuRemainder(State, 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 */ 1418 Inverse = FpuInverseNumberSine; 1419 TempResult = SeriesElement = Normalized; 1420 } 1421 else 1422 { 1423 /* This is a cosine */ 1424 Inverse = FpuInverseNumberCosine; 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 1439 if (!Fast486FpuMultiply(State, 1440 &SeriesElement, 1441 &Inverse[i], 1442 &SeriesElement)) 1443 { 1444 /* An exception occurred */ 1445 return FALSE; 1446 } 1447 1448 /* Toggle the sign of the series element */ 1449 SeriesElement.Sign = !SeriesElement.Sign; 1450 1451 if (!Fast486FpuAdd(State, &TempResult, &SeriesElement, &TempResult)) 1452 { 1453 /* An exception occurred */ 1454 return FALSE; 1455 } 1456 } 1457 1458 /* Flip the sign for the third and fourth quadrant */ 1459 if (Quadrant >= 2) TempResult.Sign = !TempResult.Sign; 1460 1461 *Result = TempResult; 1462 return TRUE; 1463 } 1464 1465 /* 1466 * Calculates using the identity: 1467 * cos(x) = sum { -1^n * x^(2n) / (2n)!, n >= 0 } 1468 */ 1469 static inline BOOLEAN FASTCALL 1470 Fast486FpuCalculateCosine(PFAST486_STATE State, 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 */ 1480 return Fast486FpuCalculateSine(State, &Value, Result); 1481 } 1482 1483 static inline VOID FASTCALL 1484 Fast486FpuArithmeticOperation(PFAST486_STATE State, 1485 INT Operation, 1486 PFAST486_FPU_DATA_REG Operand, 1487 BOOLEAN TopDestination) 1488 { 1489 PFAST486_FPU_DATA_REG DestOperand = TopDestination ? &FPU_ST(0) : Operand; 1490 1491 ASSERT(!(Operation & ~7)); 1492 1493 /* Check the operation */ 1494 switch (Operation) 1495 { 1496 /* FADD */ 1497 case 0: 1498 { 1499 Fast486FpuAdd(State, &FPU_ST(0), Operand, DestOperand); 1500 break; 1501 } 1502 1503 /* FMUL */ 1504 case 1: 1505 { 1506 Fast486FpuMultiply(State, &FPU_ST(0), Operand, DestOperand); 1507 break; 1508 } 1509 1510 /* FCOM */ 1511 case 2: 1512 /* FCOMP */ 1513 case 3: 1514 { 1515 Fast486FpuCompare(State, &FPU_ST(0), Operand); 1516 if (Operation == 3) Fast486FpuPop(State); 1517 1518 break; 1519 } 1520 1521 /* FSUB */ 1522 case 4: 1523 { 1524 Fast486FpuSubtract(State, &FPU_ST(0), Operand, DestOperand); 1525 break; 1526 } 1527 1528 /* FSUBR */ 1529 case 5: 1530 { 1531 Fast486FpuSubtract(State, Operand, &FPU_ST(0), DestOperand); 1532 break; 1533 } 1534 1535 /* FDIV */ 1536 case 6: 1537 { 1538 Fast486FpuDivide(State, &FPU_ST(0), Operand, DestOperand); 1539 break; 1540 } 1541 1542 /* FDIVR */ 1543 case 7: 1544 { 1545 Fast486FpuDivide(State, Operand, &FPU_ST(0), DestOperand); 1546 break; 1547 } 1548 } 1549 } 1550 1551 /* 1552 * Calculates using: 1553 * x[0] = s 1554 * x[n + 1] = (x[n] + s / x[n]) / 2 1555 */ 1556 static inline BOOLEAN FASTCALL 1557 Fast486FpuCalculateSquareRoot(PFAST486_STATE State, 1558 PCFAST486_FPU_DATA_REG Operand, 1559 PFAST486_FPU_DATA_REG Result) 1560 { 1561 FAST486_FPU_DATA_REG Value = *Operand; 1562 FAST486_FPU_DATA_REG PrevValue = FpuZero; 1563 1564 if (Operand->Sign) 1565 { 1566 /* Raise the invalid operation exception */ 1567 State->FpuStatus.Ie = TRUE; 1568 1569 if (State->FpuControl.Im) 1570 { 1571 /* Return the indefinite NaN */ 1572 Result->Sign = TRUE; 1573 Result->Exponent = FPU_MAX_EXPONENT + 1; 1574 Result->Mantissa = FPU_INDEFINITE_MANTISSA; 1575 return TRUE; 1576 } 1577 else 1578 { 1579 return FALSE; 1580 } 1581 } 1582 1583 /* Loop until it converges */ 1584 while (Value.Sign != PrevValue.Sign 1585 || Value.Exponent != PrevValue.Exponent 1586 || Value.Mantissa != PrevValue.Mantissa) 1587 { 1588 FAST486_FPU_DATA_REG Temp; 1589 1590 /* Save the current value */ 1591 PrevValue = Value; 1592 1593 /* Divide the operand by the current value */ 1594 if (!Fast486FpuDivide(State, Operand, &Value, &Temp)) return FALSE; 1595 1596 /* Add the result of that division to the current value */ 1597 if (!Fast486FpuAdd(State, &Value, &Temp, &Value)) return FALSE; 1598 1599 /* Halve the current value */ 1600 if (!Fast486FpuMultiply(State, &Value, &FpuInverseNumber[1], &Value)) return FALSE; 1601 } 1602 1603 *Result = Value; 1604 return TRUE; 1605 } 1606 1607 /* 1608 * Calculates arctan using Euler's formula: 1609 * arctan(x) = (x / (1 + x^2)) * sum { prod { (2j * x^2) 1610 * / ((2j + 1) * (1 + x^2)), j >= 1, j <= i }, i >= 0 } 1611 */ 1612 static inline BOOLEAN FASTCALL 1613 Fast486FpuCalculateArcTangent(PFAST486_STATE State, 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... */ 1652 if (FPU_IS_INDEFINITE(&Value)) Value = FpuZero; 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 1675 if (!Fast486FpuMultiply(State, 1676 &SeriesElement, 1677 &FpuInverseNumberAtan[i], 1678 &SeriesElement)) 1679 { 1680 /* An exception occurred */ 1681 return FALSE; 1682 } 1683 1684 if (!Fast486FpuAdd(State, &TempResult, &SeriesElement, &TempResult)) 1685 { 1686 /* An exception occurred */ 1687 return FALSE; 1688 } 1689 } 1690 1691 if (!Fast486FpuMultiply(State, &TempResult, &ValDivValSqP1, &TempResult)) 1692 { 1693 /* An exception occurred */ 1694 return FALSE; 1695 } 1696 1697 if (Inverted) 1698 { 1699 /* Since y/x is positive, arctan(y/x) = pi/2 - arctan(x/y) */ 1700 if (!Fast486FpuSubtract(State, &FpuHalfPi, &TempResult, &TempResult)) return FALSE; 1701 } 1702 1703 /* Adjust the sign */ 1704 if (!(!Numerator->Sign == !Denominator->Sign)) TempResult.Sign = !TempResult.Sign; 1705 1706 if (Denominator->Sign) 1707 { 1708 if (Numerator->Sign) 1709 { 1710 /* Subtract PI */ 1711 if (!Fast486FpuSubtract(State, &TempResult, &FpuPi, &TempResult)) return FALSE; 1712 } 1713 else 1714 { 1715 /* Add PI */ 1716 if (!Fast486FpuAdd(State, &TempResult, &FpuPi, &TempResult)) return FALSE; 1717 } 1718 } 1719 1720 *Result = TempResult; 1721 return TRUE; 1722 } 1723 1724 static inline BOOLEAN FASTCALL 1725 Fast486FpuLoadEnvironment(PFAST486_STATE State, 1726 INT Segment, 1727 ULONG Address, 1728 BOOLEAN Size) 1729 { 1730 UCHAR Buffer[28]; 1731 1732 if (!Fast486ReadMemory(State, Segment, Address, FALSE, Buffer, (Size + 1) * 14)) 1733 { 1734 /* Exception occurred */ 1735 return FALSE; 1736 } 1737 1738 /* Check if this is a 32-bit save or a 16-bit save */ 1739 if (Size) 1740 { 1741 PULONG Data = (PULONG)Buffer; 1742 1743 State->FpuControl.Value = (USHORT)Data[0]; 1744 State->FpuStatus.Value = (USHORT)Data[1]; 1745 State->FpuTag = (USHORT)Data[2]; 1746 State->FpuLastInstPtr.Long = Data[3]; 1747 State->FpuLastCodeSel = (USHORT)Data[4]; 1748 State->FpuLastOpPtr.Long = Data[5]; 1749 State->FpuLastDataSel = (USHORT)Data[6]; 1750 } 1751 else 1752 { 1753 PUSHORT Data = (PUSHORT)Buffer; 1754 1755 State->FpuControl.Value = Data[0]; 1756 State->FpuStatus.Value = Data[1]; 1757 State->FpuTag = Data[2]; 1758 State->FpuLastInstPtr.LowWord = Data[3]; 1759 State->FpuLastCodeSel = Data[4]; 1760 State->FpuLastOpPtr.LowWord = Data[5]; 1761 State->FpuLastDataSel = Data[6]; 1762 } 1763 1764 return TRUE; 1765 } 1766 1767 static inline BOOLEAN FASTCALL 1768 Fast486FpuSaveEnvironment(PFAST486_STATE State, 1769 INT Segment, 1770 ULONG Address, 1771 BOOLEAN Size) 1772 { 1773 UCHAR Buffer[28]; 1774 1775 /* Check if this is a 32-bit save or a 16-bit save */ 1776 if (Size) 1777 { 1778 PULONG Data = (PULONG)Buffer; 1779 1780 Data[0] = (ULONG)State->FpuControl.Value; 1781 Data[1] = (ULONG)State->FpuStatus.Value; 1782 Data[2] = (ULONG)State->FpuTag; 1783 Data[3] = State->FpuLastInstPtr.Long; 1784 Data[4] = (ULONG)State->FpuLastCodeSel; 1785 Data[5] = State->FpuLastOpPtr.Long; 1786 Data[6] = (ULONG)State->FpuLastDataSel; 1787 } 1788 else 1789 { 1790 PUSHORT Data = (PUSHORT)Buffer; 1791 1792 Data[0] = State->FpuControl.Value; 1793 Data[1] = State->FpuStatus.Value; 1794 Data[2] = State->FpuTag; 1795 Data[3] = State->FpuLastInstPtr.LowWord; 1796 Data[4] = State->FpuLastCodeSel; 1797 Data[5] = State->FpuLastOpPtr.LowWord; 1798 Data[6] = State->FpuLastDataSel; 1799 } 1800 1801 return Fast486WriteMemory(State, Segment, Address, Buffer, (Size + 1) * 14); 1802 } 1803 1804 #endif 1805 1806 /* PUBLIC FUNCTIONS ***********************************************************/ 1807 1808 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8) 1809 { 1810 FAST486_MOD_REG_RM ModRegRm; 1811 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 1812 #ifndef FAST486_NO_FPU 1813 PFAST486_FPU_DATA_REG Operand; 1814 FAST486_FPU_DATA_REG MemoryData; 1815 #endif 1816 1817 TOGGLE_ADSIZE(AddressSize); 1818 1819 /* Get the operands */ 1820 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 1821 { 1822 /* Exception occurred */ 1823 return; 1824 } 1825 1826 FPU_CHECK(); 1827 1828 #ifndef FAST486_NO_FPU 1829 1830 Fast486FpuExceptionCheck(State); 1831 FPU_SAVE_LAST_INST(); 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 1845 FPU_SET_TAG(0, FPU_TAG_SPECIAL); 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 1865 FPU_SAVE_LAST_OPERAND(); 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 1881 FPU_SET_TAG(0, FPU_TAG_SPECIAL); 1882 } 1883 1884 return; 1885 } 1886 1887 /* Load the source operand from an FPU register */ 1888 Operand = &FPU_ST(ModRegRm.SecondRegister); 1889 } 1890 1891 /* Perform the requested operation */ 1892 Fast486FpuArithmeticOperation(State, ModRegRm.Register, Operand, TRUE); 1893 1894 #endif 1895 } 1896 1897 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9) 1898 { 1899 FAST486_MOD_REG_RM ModRegRm; 1900 BOOLEAN OperandSize, AddressSize; 1901 1902 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 1903 TOGGLE_OPSIZE(OperandSize); 1904 TOGGLE_ADSIZE(AddressSize); 1905 1906 /* Get the operands */ 1907 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 1908 { 1909 /* Exception occurred */ 1910 return; 1911 } 1912 1913 FPU_CHECK(); 1914 1915 #ifndef FAST486_NO_FPU 1916 1917 if (ModRegRm.Memory) 1918 { 1919 switch (ModRegRm.Register) 1920 { 1921 /* FLD */ 1922 case 0: 1923 { 1924 ULONG Value; 1925 FAST486_FPU_DATA_REG MemoryData; 1926 1927 Fast486FpuExceptionCheck(State); 1928 FPU_SAVE_LAST_INST(); 1929 FPU_SAVE_LAST_OPERAND(); 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 { 1948 ULONG Value = FPU_REAL4_INDEFINITE; 1949 1950 Fast486FpuExceptionCheck(State); 1951 FPU_SAVE_LAST_INST(); 1952 FPU_SAVE_LAST_OPERAND(); 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 { 1983 Fast486FpuLoadEnvironment(State, 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 { 2001 Fast486FpuSaveEnvironment(State, 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); 2039 FPU_SAVE_LAST_INST(); 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); 2069 FPU_SAVE_LAST_INST(); 2070 2071 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) 2072 || FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY) 2073 { 2074 State->FpuStatus.Ie = TRUE; 2075 break; 2076 } 2077 2078 /* Exchange */ 2079 Temp = FPU_ST(0); 2080 FPU_ST(0) = FPU_ST(ModRegRm.SecondRegister); 2081 FPU_ST(ModRegRm.SecondRegister) = Temp; 2082 2083 FPU_UPDATE_TAG(0); 2084 FPU_UPDATE_TAG(ModRegRm.SecondRegister); 2085 2086 break; 2087 } 2088 2089 /* FNOP */ 2090 case 0x10: 2091 { 2092 /* Do nothing */ 2093 break; 2094 } 2095 2096 /* FSTP */ 2097 case 0x18: 2098 case 0x19: 2099 case 0x1A: 2100 case 0x1B: 2101 case 0x1C: 2102 case 0x1D: 2103 case 0x1E: 2104 case 0x1F: 2105 { 2106 Fast486FpuExceptionCheck(State); 2107 FPU_SAVE_LAST_INST(); 2108 2109 FPU_ST(ModRegRm.SecondRegister) = FPU_ST(0); 2110 FPU_UPDATE_TAG(ModRegRm.SecondRegister); 2111 2112 Fast486FpuPop(State); 2113 break; 2114 } 2115 2116 /* FCHS */ 2117 case 0x20: 2118 { 2119 Fast486FpuExceptionCheck(State); 2120 FPU_SAVE_LAST_INST(); 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); 2138 FPU_SAVE_LAST_INST(); 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); 2156 FPU_SAVE_LAST_INST(); 2157 2158 Fast486FpuCompare(State, &FPU_ST(0), &FpuZero); 2159 break; 2160 } 2161 2162 /* FXAM */ 2163 case 0x25: 2164 { 2165 Fast486FpuExceptionCheck(State); 2166 FPU_SAVE_LAST_INST(); 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); 2244 FPU_SAVE_LAST_INST(); 2245 2246 Fast486FpuPush(State, Constants[ModRegRm.SecondRegister]); 2247 break; 2248 } 2249 2250 /* F2XM1 */ 2251 case 0x30: 2252 { 2253 Fast486FpuExceptionCheck(State); 2254 FPU_SAVE_LAST_INST(); 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 2272 Fast486FpuCalculateTwoPowerMinusOne(State, &FPU_ST(0), &FPU_ST(0)); 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); 2284 FPU_SAVE_LAST_INST(); 2285 2286 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY || FPU_GET_TAG(1) == FPU_TAG_EMPTY) 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); 2319 FPU_SAVE_LAST_INST(); 2320 2321 /* Compute the sine */ 2322 if (!Fast486FpuCalculateSine(State, &FPU_ST(0), &Sine)) break; 2323 2324 /* Normalize the angle */ 2325 if (!Fast486FpuRemainder(State, 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); 2359 FPU_SAVE_LAST_INST(); 2360 2361 if (!Fast486FpuCalculateArcTangent(State, 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); 2381 FPU_SAVE_LAST_INST(); 2382 2383 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || FPU_IS_INDEFINITE(&Value)) 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 */ 2407 Fast486FpuFromInteger(State, 2408 (LONGLONG)Value.Exponent - (LONGLONG)FPU_REAL10_BIAS, 2409 &FPU_ST(0)); 2410 } 2411 2412 /* Now push the mantissa as a real number, with the original sign */ 2413 Value.Exponent = FPU_REAL10_BIAS; 2414 Fast486FpuPush(State, &Value); 2415 2416 break; 2417 } 2418 2419 /* FPREM1 */ 2420 case 0x35: 2421 /* FPREM */ 2422 case 0x38: 2423 { 2424 LONGLONG Quotient; 2425 2426 Fast486FpuExceptionCheck(State); 2427 FPU_SAVE_LAST_INST(); 2428 2429 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY || FPU_GET_TAG(1) == FPU_TAG_EMPTY) 2430 { 2431 State->FpuStatus.Ie = TRUE; 2432 break; 2433 } 2434 2435 if (Fast486FpuRemainder(State, 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); 2473 FPU_SAVE_LAST_INST(); 2474 2475 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY || FPU_GET_TAG(1) == FPU_TAG_EMPTY) 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); 2510 FPU_SAVE_LAST_INST(); 2511 2512 Fast486FpuCalculateSquareRoot(State, &FPU_ST(0), &FPU_ST(0)); 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); 2524 FPU_SAVE_LAST_INST(); 2525 2526 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY) 2527 { 2528 State->FpuStatus.Ie = TRUE; 2529 break; 2530 } 2531 2532 if (!FPU_IS_NORMALIZED(&FPU_ST(0))) 2533 { 2534 State->FpuStatus.De = TRUE; 2535 2536 if (!State->FpuControl.Dm) 2537 { 2538 break; 2539 } 2540 } 2541 2542 /* Replace FP0 with the sine */ 2543 if (!Fast486FpuCalculateSine(State, &Number, &FPU_ST(0))) break; 2544 FPU_UPDATE_TAG(0); 2545 2546 /* Push the cosine */ 2547 if (!Fast486FpuCalculateCosine(State, &Number, &Number)) break; 2548 Fast486FpuPush(State, &Number); 2549 2550 break; 2551 } 2552 2553 /* FRNDINT */ 2554 case 0x3C: 2555 { 2556 LONGLONG Result = 0LL; 2557 2558 Fast486FpuExceptionCheck(State); 2559 FPU_SAVE_LAST_INST(); 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 */ 2581 Fast486FpuToInteger(State, &FPU_ST(0), &Result); 2582 Fast486FpuFromInteger(State, Result, &FPU_ST(0)); 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); 2596 FPU_SAVE_LAST_INST(); 2597 2598 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY || FPU_GET_TAG(1) == FPU_TAG_EMPTY) 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); 2671 FPU_SAVE_LAST_INST(); 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 2689 Fast486FpuCalculateSine(State, &FPU_ST(0), &FPU_ST(0)); 2690 FPU_UPDATE_TAG(0); 2691 2692 break; 2693 } 2694 2695 /* FCOS */ 2696 case 0x3F: 2697 { 2698 Fast486FpuExceptionCheck(State); 2699 FPU_SAVE_LAST_INST(); 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 2717 Fast486FpuCalculateCosine(State, &FPU_ST(0), &FPU_ST(0)); 2718 FPU_UPDATE_TAG(0); 2719 2720 break; 2721 } 2722 2723 /* Invalid */ 2724 default: 2725 { 2726 Fast486Exception(State, FAST486_EXCEPTION_UD); 2727 return; 2728 } 2729 } 2730 } 2731 2732 #endif 2733 } 2734 2735 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA) 2736 { 2737 FAST486_MOD_REG_RM ModRegRm; 2738 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 2739 #ifndef FAST486_NO_FPU 2740 LONG Value; 2741 FAST486_FPU_DATA_REG MemoryData; 2742 #endif 2743 2744 TOGGLE_ADSIZE(AddressSize); 2745 2746 /* Get the operands */ 2747 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 2748 { 2749 /* Exception occurred */ 2750 return; 2751 } 2752 2753 FPU_CHECK(); 2754 2755 #ifndef FAST486_NO_FPU 2756 2757 Fast486FpuExceptionCheck(State); 2758 FPU_SAVE_LAST_INST(); 2759 2760 if (!ModRegRm.Memory) 2761 { 2762 /* The only valid opcode in this case is FUCOMPP (0xDA 0xE9) */ 2763 if ((ModRegRm.Register != 5) && (ModRegRm.SecondRegister != 1)) 2764 { 2765 Fast486Exception(State, FAST486_EXCEPTION_UD); 2766 return; 2767 } 2768 2769 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(1) == FPU_TAG_EMPTY)) 2770 { 2771 /* Raise the invalid operation exception*/ 2772 State->FpuStatus.Ie = TRUE; 2773 return; 2774 } 2775 2776 /* Compare */ 2777 Fast486FpuCompare(State, &FPU_ST(0), &FPU_ST(1)); 2778 2779 /* Pop twice */ 2780 Fast486FpuPop(State); 2781 Fast486FpuPop(State); 2782 2783 return; 2784 } 2785 2786 FPU_SAVE_LAST_OPERAND(); 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 2807 FPU_SET_TAG(0, FPU_TAG_SPECIAL); 2808 } 2809 2810 return; 2811 } 2812 2813 Fast486FpuFromInteger(State, (LONGLONG)Value, &MemoryData); 2814 2815 /* Perform the requested operation */ 2816 Fast486FpuArithmeticOperation(State, ModRegRm.Register, &MemoryData, TRUE); 2817 2818 #endif 2819 } 2820 2821 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB) 2822 { 2823 FAST486_MOD_REG_RM ModRegRm; 2824 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 2825 2826 TOGGLE_ADSIZE(AddressSize); 2827 2828 /* Get the operands */ 2829 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 2830 { 2831 /* Exception occurred */ 2832 return; 2833 } 2834 2835 FPU_CHECK(); 2836 2837 #ifndef FAST486_NO_FPU 2838 2839 if (ModRegRm.Memory) 2840 { 2841 Fast486FpuExceptionCheck(State); 2842 FPU_SAVE_LAST_INST(); 2843 FPU_SAVE_LAST_OPERAND(); 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 2859 Fast486FpuFromInteger(State, (LONGLONG)Value, &Temp); 2860 Fast486FpuPush(State, &Temp); 2861 2862 break; 2863 } 2864 2865 /* FIST */ 2866 case 2: 2867 /* FISTP */ 2868 case 3: 2869 { 2870 LONGLONG Temp = 0; 2871 2872 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL)) 2873 { 2874 /* Raise the invalid operation exception */ 2875 State->FpuStatus.Ie = TRUE; 2876 2877 if (!State->FpuControl.Im) 2878 { 2879 return; 2880 } 2881 } 2882 2883 if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp)) 2884 { 2885 /* Exception occurred */ 2886 return; 2887 } 2888 2889 /* Check if it can fit in a signed 32-bit integer */ 2890 if ((LONGLONG)((LONG)Temp) != Temp) 2891 { 2892 State->FpuStatus.Ie = TRUE; 2893 2894 if (State->FpuControl.Im) 2895 { 2896 Temp = 0x80000000LL; 2897 } 2898 else 2899 { 2900 return; 2901 } 2902 } 2903 2904 if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, (ULONG)((LONG)Temp))) 2905 { 2906 /* Exception occurred */ 2907 return; 2908 } 2909 2910 if (ModRegRm.Register == 3) 2911 { 2912 /* Pop the FPU stack too */ 2913 Fast486FpuPop(State); 2914 } 2915 2916 break; 2917 } 2918 2919 /* FLD */ 2920 case 5: 2921 { 2922 FAST486_FPU_DATA_REG Value; 2923 UCHAR Buffer[10]; 2924 2925 if (!Fast486ReadMemory(State, 2926 (State->PrefixFlags & FAST486_PREFIX_SEG) 2927 ? State->SegmentOverride : FAST486_REG_DS, 2928 ModRegRm.MemoryAddress, 2929 FALSE, 2930 Buffer, 2931 sizeof(Buffer))) 2932 { 2933 /* Exception occurred */ 2934 return; 2935 } 2936 2937 Value.Mantissa = *((PULONGLONG)Buffer); 2938 Value.Exponent = *((PUSHORT)&Buffer[8]) & (FPU_MAX_EXPONENT + 1); 2939 Value.Sign = *((PUCHAR)&Buffer[9]) >> 7; 2940 2941 Fast486FpuPush(State, &Value); 2942 break; 2943 } 2944 2945 /* FSTP */ 2946 case 7: 2947 { 2948 UCHAR Buffer[10]; 2949 2950 if (FPU_GET_TAG(0) != FPU_TAG_EMPTY) 2951 { 2952 *((PULONGLONG)Buffer) = FPU_ST(0).Mantissa; 2953 *((PUSHORT)&Buffer[sizeof(ULONGLONG)]) = FPU_ST(0).Exponent 2954 | (FPU_ST(0).Sign ? 0x8000 : 0); 2955 } 2956 else 2957 { 2958 /* Raise the invalid operation exception */ 2959 State->FpuStatus.Ie = TRUE; 2960 2961 if (State->FpuControl.Im) 2962 { 2963 *((PULONGLONG)Buffer) = FPU_INDEFINITE_MANTISSA; 2964 *((PUSHORT)&Buffer[sizeof(ULONGLONG)]) = 0x8000 | (FPU_MAX_EXPONENT + 1); 2965 } 2966 else 2967 { 2968 return; 2969 } 2970 } 2971 2972 if (!Fast486WriteMemory(State, 2973 (State->PrefixFlags & FAST486_PREFIX_SEG) 2974 ? State->SegmentOverride : FAST486_REG_DS, 2975 ModRegRm.MemoryAddress, 2976 Buffer, 2977 sizeof(Buffer))) 2978 { 2979 /* Exception occurred */ 2980 return; 2981 } 2982 2983 Fast486FpuPop(State); 2984 break; 2985 } 2986 2987 /* Invalid */ 2988 default: 2989 { 2990 Fast486Exception(State, FAST486_EXCEPTION_UD); 2991 return; 2992 } 2993 } 2994 } 2995 else 2996 { 2997 /* Only a few of these instructions have any meaning on a 487 */ 2998 switch ((ModRegRm.Register << 3) | ModRegRm.SecondRegister) 2999 { 3000 /* FCLEX */ 3001 case 0x22: 3002 { 3003 /* Clear exception data */ 3004 State->FpuStatus.Ie = 3005 State->FpuStatus.De = 3006 State->FpuStatus.Ze = 3007 State->FpuStatus.Oe = 3008 State->FpuStatus.Ue = 3009 State->FpuStatus.Pe = 3010 State->FpuStatus.Sf = 3011 State->FpuStatus.Es = 3012 State->FpuStatus.Busy = FALSE; 3013 3014 break; 3015 } 3016 3017 /* FINIT */ 3018 case 0x23: 3019 { 3020 /* Restore the state */ 3021 State->FpuControl.Value = FAST486_FPU_DEFAULT_CONTROL; 3022 State->FpuStatus.Value = 0; 3023 State->FpuTag = 0xFFFF; 3024 3025 break; 3026 } 3027 3028 /* FENI */ 3029 case 0x20: 3030 /* FDISI */ 3031 case 0x21: 3032 /* FSETPM */ 3033 case 0x24: 3034 /* FRSTPM */ 3035 case 0x25: 3036 { 3037 /* These do nothing */ 3038 break; 3039 } 3040 3041 /* Invalid */ 3042 default: 3043 { 3044 Fast486Exception(State, FAST486_EXCEPTION_UD); 3045 return; 3046 } 3047 } 3048 } 3049 3050 #endif 3051 } 3052 3053 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDC) 3054 { 3055 FAST486_MOD_REG_RM ModRegRm; 3056 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 3057 #ifndef FAST486_NO_FPU 3058 PFAST486_FPU_DATA_REG Operand; 3059 FAST486_FPU_DATA_REG MemoryData; 3060 #endif 3061 3062 TOGGLE_ADSIZE(AddressSize); 3063 3064 /* Get the operands */ 3065 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 3066 { 3067 /* Exception occurred */ 3068 return; 3069 } 3070 3071 FPU_CHECK(); 3072 3073 #ifndef FAST486_NO_FPU 3074 3075 Fast486FpuExceptionCheck(State); 3076 FPU_SAVE_LAST_INST(); 3077 3078 if (ModRegRm.Memory) 3079 { 3080 ULONGLONG Value; 3081 3082 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY) 3083 { 3084 /* Raise the invalid operation exception */ 3085 State->FpuStatus.Ie = TRUE; 3086 3087 if (State->FpuControl.Im) 3088 { 3089 /* Return the indefinite NaN */ 3090 FPU_ST(0).Sign = TRUE; 3091 FPU_ST(0).Exponent = FPU_MAX_EXPONENT + 1; 3092 FPU_ST(0).Mantissa = FPU_INDEFINITE_MANTISSA; 3093 3094 FPU_SET_TAG(0, FPU_TAG_SPECIAL); 3095 } 3096 3097 return; 3098 } 3099 3100 /* Load the source operand from memory */ 3101 if (!Fast486ReadMemory(State, 3102 (State->PrefixFlags & FAST486_PREFIX_SEG) 3103 ? State->SegmentOverride : FAST486_REG_DS, 3104 ModRegRm.MemoryAddress, 3105 FALSE, 3106 &Value, 3107 sizeof(ULONGLONG))) 3108 { 3109 /* Exception occurred */ 3110 return; 3111 } 3112 3113 Fast486FpuFromDoubleReal(State, Value, &MemoryData); 3114 Operand = &MemoryData; 3115 3116 FPU_SAVE_LAST_OPERAND(); 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 3136 FPU_SET_TAG(ModRegRm.SecondRegister, FPU_TAG_SPECIAL); 3137 } 3138 3139 return; 3140 } 3141 } 3142 3143 /* Perform the requested operation */ 3144 Fast486FpuArithmeticOperation(State, ModRegRm.Register, Operand, ModRegRm.Memory); 3145 3146 #endif 3147 } 3148 3149 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDD) 3150 { 3151 FAST486_MOD_REG_RM ModRegRm; 3152 BOOLEAN OperandSize, AddressSize; 3153 3154 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 3155 TOGGLE_OPSIZE(OperandSize); 3156 TOGGLE_ADSIZE(AddressSize); 3157 3158 /* Get the operands */ 3159 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 3160 { 3161 /* Exception occurred */ 3162 return; 3163 } 3164 3165 FPU_CHECK(); 3166 3167 #ifndef FAST486_NO_FPU 3168 3169 if (ModRegRm.Memory) 3170 { 3171 switch (ModRegRm.Register) 3172 { 3173 /* FLD */ 3174 case 0: 3175 { 3176 ULONGLONG Value; 3177 FAST486_FPU_DATA_REG MemoryData; 3178 3179 Fast486FpuExceptionCheck(State); 3180 FPU_SAVE_LAST_INST(); 3181 FPU_SAVE_LAST_OPERAND(); 3182 3183 if (!Fast486ReadMemory(State, 3184 (State->PrefixFlags & FAST486_PREFIX_SEG) 3185 ? State->SegmentOverride : FAST486_REG_DS, 3186 ModRegRm.MemoryAddress, 3187 FALSE, 3188 &Value, 3189 sizeof(ULONGLONG))) 3190 { 3191 /* Exception occurred */ 3192 return; 3193 } 3194 3195 Fast486FpuFromDoubleReal(State, Value, &MemoryData); 3196 Fast486FpuPush(State, &MemoryData); 3197 3198 break; 3199 } 3200 3201 /* FST */ 3202 case 2: 3203 /* FSTP */ 3204 case 3: 3205 { 3206 ULONGLONG Value = FPU_REAL8_INDEFINITE; 3207 3208 Fast486FpuExceptionCheck(State); 3209 FPU_SAVE_LAST_INST(); 3210 FPU_SAVE_LAST_OPERAND(); 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 3228 if (!Fast486WriteMemory(State, 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 */ 3250 if (!Fast486FpuLoadEnvironment(State, 3251 (State->PrefixFlags & FAST486_PREFIX_SEG) 3252 ? State->SegmentOverride : FAST486_REG_DS, 3253 ModRegRm.MemoryAddress, 3254 OperandSize)) 3255 { 3256 /* Exception occurred */ 3257 return; 3258 } 3259 3260 /* Load the registers */ 3261 if (!Fast486ReadMemory(State, 3262 (State->PrefixFlags & FAST486_PREFIX_SEG) 3263 ? State->SegmentOverride : FAST486_REG_DS, 3264 ModRegRm.MemoryAddress + (OperandSize + 1) * 14, 3265 FALSE, 3266 AllRegs, 3267 sizeof(AllRegs))) 3268 { 3269 /* Exception occurred */ 3270 return; 3271 } 3272 3273 for (i = 0; i < FAST486_NUM_FPU_REGS; i++) 3274 { 3275 State->FpuRegisters[i].Mantissa = *((PULONGLONG)&AllRegs[i * 10]); 3276 State->FpuRegisters[i].Exponent = *((PUSHORT)&AllRegs[(i * 10) + sizeof(ULONGLONG)]) & 0x7FFF; 3277 3278 if (*((PUSHORT)&AllRegs[(i * 10) + sizeof(ULONGLONG)]) & 0x8000) 3279 { 3280 State->FpuRegisters[i].Sign = TRUE; 3281 } 3282 else 3283 { 3284 State->FpuRegisters[i].Sign = FALSE; 3285 } 3286 } 3287 3288 break; 3289 } 3290 3291 /* FSAVE */ 3292 case 6: 3293 { 3294 INT i; 3295 UCHAR AllRegs[80]; 3296 3297 /* Save the environment */ 3298 if (!Fast486FpuSaveEnvironment(State, 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 3320 Fast486WriteMemory(State, 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 { 3351 FPU_SET_TAG(ModRegRm.SecondRegister, FPU_TAG_EMPTY); 3352 break; 3353 } 3354 3355 /* FXCH */ 3356 case 1: 3357 { 3358 FAST486_FPU_DATA_REG Temp; 3359 3360 FPU_SAVE_LAST_INST(); 3361 Fast486FpuExceptionCheck(State); 3362 3363 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) 3364 || FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY) 3365 { 3366 State->FpuStatus.Ie = TRUE; 3367 break; 3368 } 3369 3370 /* Exchange */ 3371 Temp = FPU_ST(0); 3372 FPU_ST(0) = FPU_ST(ModRegRm.SecondRegister); 3373 FPU_ST(ModRegRm.SecondRegister) = Temp; 3374 3375 FPU_UPDATE_TAG(0); 3376 FPU_UPDATE_TAG(ModRegRm.SecondRegister); 3377 3378 break; 3379 } 3380 3381 /* FST */ 3382 case 2: 3383 /* FSTP */ 3384 case 3: 3385 { 3386 FPU_SAVE_LAST_INST(); 3387 Fast486FpuExceptionCheck(State); 3388 3389 FPU_ST(ModRegRm.SecondRegister) = FPU_ST(0); 3390 FPU_UPDATE_TAG(ModRegRm.SecondRegister); 3391 3392 if (ModRegRm.Register == 3) Fast486FpuPop(State); 3393 break; 3394 } 3395 3396 /* FUCOM */ 3397 case 4: 3398 /* FUCOMP */ 3399 case 5: 3400 { 3401 FPU_SAVE_LAST_INST(); 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 3411 Fast486FpuCompare(State, &FPU_ST(0), &FPU_ST(ModRegRm.SecondRegister)); 3412 if (ModRegRm.Register == 5) Fast486FpuPop(State); 3413 3414 break; 3415 } 3416 3417 /* Invalid */ 3418 default: 3419 { 3420 Fast486Exception(State, FAST486_EXCEPTION_UD); 3421 } 3422 } 3423 } 3424 3425 #endif 3426 } 3427 3428 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDE) 3429 { 3430 FAST486_MOD_REG_RM ModRegRm; 3431 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 3432 #ifndef FAST486_NO_FPU 3433 PFAST486_FPU_DATA_REG Operand; 3434 FAST486_FPU_DATA_REG MemoryData; 3435 #endif 3436 3437 TOGGLE_ADSIZE(AddressSize); 3438 3439 /* Get the operands */ 3440 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 3441 { 3442 /* Exception occurred */ 3443 return; 3444 } 3445 3446 FPU_CHECK(); 3447 3448 #ifndef FAST486_NO_FPU 3449 3450 FPU_SAVE_LAST_INST(); 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 3469 FPU_SET_TAG(0, FPU_TAG_SPECIAL); 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 3485 FPU_SAVE_LAST_OPERAND(); 3486 } 3487 else 3488 { 3489 /* FCOMPP check */ 3490 if ((ModRegRm.Register == 3) && (ModRegRm.SecondRegister != 1)) 3491 { 3492 /* Invalid */ 3493 Fast486Exception(State, FAST486_EXCEPTION_UD); 3494 return; 3495 } 3496 3497 /* Load the destination operand from a register */ 3498 Operand = &FPU_ST(ModRegRm.SecondRegister); 3499 3500 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) 3501 || (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)) 3502 { 3503 /* Raise the invalid operation exception, if unmasked */ 3504 State->FpuStatus.Ie = TRUE; 3505 return; 3506 } 3507 } 3508 3509 /* Perform the requested operation */ 3510 Fast486FpuArithmeticOperation(State, ModRegRm.Register, Operand, ModRegRm.Memory); 3511 if (!ModRegRm.Memory) Fast486FpuPop(State); 3512 3513 #endif 3514 } 3515 3516 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF) 3517 { 3518 FAST486_MOD_REG_RM ModRegRm; 3519 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 3520 3521 TOGGLE_ADSIZE(AddressSize); 3522 3523 /* Get the operands */ 3524 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 3525 { 3526 /* Exception occurred */ 3527 return; 3528 } 3529 3530 FPU_CHECK(); 3531 3532 #ifndef FAST486_NO_FPU 3533 3534 FPU_SAVE_LAST_INST(); 3535 Fast486FpuExceptionCheck(State); 3536 3537 if (ModRegRm.Memory) 3538 { 3539 FPU_SAVE_LAST_OPERAND(); 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 3555 Fast486FpuFromInteger(State, (LONGLONG)Value, &Temp); 3556 Fast486FpuPush(State, &Temp); 3557 3558 break; 3559 } 3560 3561 /* FIST */ 3562 case 2: 3563 /* FISTP */ 3564 case 3: 3565 { 3566 LONGLONG Temp = 0LL; 3567 3568 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL)) 3569 { 3570 /* Raise the invalid operation exception */ 3571 State->FpuStatus.Ie = TRUE; 3572 3573 if (!State->FpuControl.Im) 3574 { 3575 return; 3576 } 3577 } 3578 3579 if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp)) 3580 { 3581 /* Exception occurred */ 3582 return; 3583 } 3584 3585 /* Check if it can fit in a signed 16-bit integer */ 3586 if ((LONGLONG)((SHORT)Temp) != Temp) 3587 { 3588 /* Raise the invalid operation exception */ 3589 State->FpuStatus.Ie = TRUE; 3590 3591 if (State->FpuControl.Im) 3592 { 3593 Temp = 0x8000LL; 3594 } 3595 else 3596 { 3597 return; 3598 } 3599 } 3600 3601 if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, (USHORT)((SHORT)Temp))) 3602 { 3603 /* Exception occurred */ 3604 return; 3605 } 3606 3607 if (ModRegRm.Register == 3) 3608 { 3609 /* Pop the FPU stack too */ 3610 Fast486FpuPop(State); 3611 } 3612 3613 break; 3614 } 3615 3616 /* FBLD */ 3617 case 4: 3618 { 3619 FAST486_FPU_DATA_REG Value; 3620 UCHAR Buffer[10]; 3621 3622 if (!Fast486ReadMemory(State, 3623 (State->PrefixFlags & FAST486_PREFIX_SEG) 3624 ? State->SegmentOverride : FAST486_REG_DS, 3625 ModRegRm.MemoryAddress, 3626 FALSE, 3627 Buffer, 3628 sizeof(Buffer))) 3629 { 3630 /* Exception occurred */ 3631 return; 3632 } 3633 3634 Fast486FpuFromPackedBcd(State, Buffer, &Value); 3635 Fast486FpuPush(State, &Value); 3636 3637 break; 3638 } 3639 3640 /* FILD (64-bit int) */ 3641 case 5: 3642 { 3643 LONGLONG Value; 3644 FAST486_FPU_DATA_REG Temp; 3645 3646 if (!Fast486ReadMemory(State, 3647 (State->PrefixFlags & FAST486_PREFIX_SEG) 3648 ? State->SegmentOverride : FAST486_REG_DS, 3649 ModRegRm.MemoryAddress, 3650 FALSE, 3651 &Value, 3652 sizeof(LONGLONG))) 3653 { 3654 /* Exception occurred */ 3655 return; 3656 } 3657 3658 Fast486FpuFromInteger(State, (LONGLONG)Value, &Temp); 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 3685 if (!Fast486WriteMemory(State, 3686 (State->PrefixFlags & FAST486_PREFIX_SEG) 3687 ? State->SegmentOverride : FAST486_REG_DS, 3688 ModRegRm.MemoryAddress, 3689 Buffer, 3690 sizeof(Buffer))) 3691 { 3692 /* Exception occurred */ 3693 return; 3694 } 3695 3696 Fast486FpuPop(State); 3697 break; 3698 } 3699 3700 /* FISTP (64-bit int) */ 3701 case 7: 3702 { 3703 LONGLONG Temp = 0LL; 3704 3705 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL)) 3706 { 3707 /* Raise the invalid operation exception */ 3708 State->FpuStatus.Ie = TRUE; 3709 3710 if (!State->FpuControl.Im) 3711 { 3712 return; 3713 } 3714 } 3715 3716 if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp)) 3717 { 3718 /* Exception occurred */ 3719 return; 3720 } 3721 3722 if (!Fast486WriteMemory(State, 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 { 3753 FPU_SET_TAG(ModRegRm.SecondRegister, FPU_TAG_EMPTY); 3754 Fast486FpuPop(State); 3755 3756 break; 3757 } 3758 3759 /* FXCH */ 3760 case 1: 3761 { 3762 FAST486_FPU_DATA_REG Temp; 3763 3764 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) 3765 || FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY) 3766 { 3767 State->FpuStatus.Ie = TRUE; 3768 break; 3769 } 3770 3771 /* Exchange */ 3772 Temp = FPU_ST(0); 3773 FPU_ST(0) = FPU_ST(ModRegRm.SecondRegister); 3774 FPU_ST(ModRegRm.SecondRegister) = Temp; 3775 3776 FPU_UPDATE_TAG(0); 3777 FPU_UPDATE_TAG(ModRegRm.SecondRegister); 3778 3779 break; 3780 } 3781 3782 /* FSTP */ 3783 case 2: 3784 case 3: 3785 { 3786 FPU_ST(ModRegRm.SecondRegister) = FPU_ST(0); 3787 FPU_UPDATE_TAG(ModRegRm.SecondRegister); 3788 Fast486FpuPop(State); 3789 3790 break; 3791 } 3792 3793 /* FSTSW */ 3794 case 4: 3795 { 3796 if (ModRegRm.SecondRegister != 0) 3797 { 3798 /* Invalid */ 3799 Fast486Exception(State, FAST486_EXCEPTION_UD); 3800 return; 3801 } 3802 3803 /* Store the status word in AX */ 3804 State->GeneralRegs[FAST486_REG_EAX].LowWord = State->FpuStatus.Value; 3805 3806 break; 3807 } 3808 3809 /* Invalid */ 3810 default: 3811 { 3812 Fast486Exception(State, FAST486_EXCEPTION_UD); 3813 return; 3814 } 3815 } 3816 } 3817 3818 #endif 3819 } 3820 3821 /* EOF */ 3822