DOSBox-X
|
00001 /* 00002 * Copyright (C) 2002-2020 The DOSBox Team 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License along 00015 * with this program; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 00019 00020 00021 // #define WEAK_EXCEPTIONS 00022 00023 00024 #if defined (_MSC_VER) 00025 00026 #ifdef WEAK_EXCEPTIONS 00027 #define clx 00028 #else 00029 #define clx fclex 00030 #endif 00031 00032 #ifdef WEAK_EXCEPTIONS 00033 #define FPUD_LOAD(op,szI,szA) \ 00034 __asm { \ 00035 __asm mov ebx, store_to \ 00036 __asm shl ebx, 4 \ 00037 __asm op szI PTR fpu.p_regs[128].m1 \ 00038 __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ 00039 } 00040 #else 00041 #define FPUD_LOAD(op,szI,szA) \ 00042 Bit16u new_sw; \ 00043 __asm { \ 00044 __asm mov eax, 8 \ 00045 __asm shl eax, 4 \ 00046 __asm mov ebx, store_to \ 00047 __asm shl ebx, 4 \ 00048 __asm fclex \ 00049 __asm op szI PTR fpu.p_regs[eax].m1 \ 00050 __asm fnstsw new_sw \ 00051 __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ 00052 } \ 00053 fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); 00054 #endif 00055 00056 #ifdef WEAK_EXCEPTIONS 00057 #define FPUD_LOAD_EA(op,szI,szA) \ 00058 __asm { \ 00059 __asm op szI PTR fpu.p_regs[128].m1 \ 00060 } 00061 #else 00062 #define FPUD_LOAD_EA(op,szI,szA) \ 00063 Bit16u new_sw; \ 00064 __asm { \ 00065 __asm mov eax, 8 \ 00066 __asm shl eax, 4 \ 00067 __asm fclex \ 00068 __asm op szI PTR fpu.p_regs[eax].m1 \ 00069 __asm fnstsw new_sw \ 00070 } \ 00071 fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); 00072 #endif 00073 00074 #ifdef WEAK_EXCEPTIONS 00075 #define FPUD_STORE(op,szI,szA) \ 00076 Bit16u save_cw; \ 00077 __asm { \ 00078 __asm fnstcw save_cw \ 00079 __asm mov eax, TOP \ 00080 __asm fldcw fpu.cw_mask_all \ 00081 __asm shl eax, 4 \ 00082 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00083 __asm op szI PTR fpu.p_regs[128].m1 \ 00084 __asm fldcw save_cw \ 00085 } 00086 #else 00087 #define FPUD_STORE(op,szI,szA) \ 00088 Bit16u new_sw,save_cw; \ 00089 __asm { \ 00090 __asm fnstcw save_cw \ 00091 __asm fldcw fpu.cw_mask_all \ 00092 __asm mov eax, TOP \ 00093 __asm shl eax, 4 \ 00094 __asm mov ebx, 8 \ 00095 __asm shl ebx, 4 \ 00096 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00097 __asm clx \ 00098 __asm op szI PTR fpu.p_regs[ebx].m1 \ 00099 __asm fnstsw new_sw \ 00100 __asm fldcw save_cw \ 00101 } \ 00102 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00103 #endif 00104 00105 // handles fsin,fcos,f2xm1,fchs,fabs 00106 #define FPUD_TRIG(op) \ 00107 Bit16u new_sw; \ 00108 __asm { \ 00109 __asm mov eax, TOP \ 00110 __asm shl eax, 4 \ 00111 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00112 __asm clx \ 00113 __asm op \ 00114 __asm fnstsw new_sw \ 00115 __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ 00116 } \ 00117 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00118 00119 // handles fsincos 00120 #define FPUD_SINCOS() \ 00121 Bit16u new_sw; \ 00122 __asm { \ 00123 __asm mov eax, TOP \ 00124 __asm mov ebx, eax \ 00125 __asm dec ebx \ 00126 __asm and ebx, 7 \ 00127 __asm shl eax, 4 \ 00128 __asm shl ebx, 4 \ 00129 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00130 __asm clx \ 00131 __asm fsincos \ 00132 __asm fnstsw new_sw \ 00133 __asm mov cx, new_sw \ 00134 __asm and ch, 0x04 \ 00135 __asm jnz argument_too_large1 \ 00136 __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ 00137 __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ 00138 __asm jmp end_sincos \ 00139 __asm argument_too_large1: \ 00140 __asm fstp st(0) \ 00141 __asm end_sincos: \ 00142 } \ 00143 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); \ 00144 if ((new_sw&0x0400)==0) FPU_PREP_PUSH(); 00145 00146 // handles fptan 00147 #define FPUD_PTAN() \ 00148 Bit16u new_sw; \ 00149 __asm { \ 00150 __asm mov eax, TOP \ 00151 __asm mov ebx, eax \ 00152 __asm dec ebx \ 00153 __asm and ebx, 7 \ 00154 __asm shl eax, 4 \ 00155 __asm shl ebx, 4 \ 00156 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00157 __asm clx \ 00158 __asm fptan \ 00159 __asm fnstsw new_sw \ 00160 __asm mov cx, new_sw \ 00161 __asm and ch, 0x04 \ 00162 __asm jnz argument_too_large2 \ 00163 __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ 00164 __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ 00165 __asm jmp end_ptan \ 00166 __asm argument_too_large2: \ 00167 __asm fstp st(0) \ 00168 __asm end_ptan: \ 00169 } \ 00170 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); \ 00171 if ((new_sw&0x0400)==0) FPU_PREP_PUSH(); 00172 00173 // handles fxtract 00174 #ifdef WEAK_EXCEPTIONS 00175 #define FPUD_XTRACT \ 00176 __asm { \ 00177 __asm mov eax, TOP \ 00178 __asm mov ebx, eax \ 00179 __asm dec ebx \ 00180 __asm and ebx, 7 \ 00181 __asm shl eax, 4 \ 00182 __asm shl ebx, 4 \ 00183 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00184 __asm fxtract \ 00185 __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ 00186 __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ 00187 } \ 00188 FPU_PREP_PUSH(); 00189 #else 00190 #define FPUD_XTRACT \ 00191 Bit16u new_sw; \ 00192 __asm { \ 00193 __asm mov eax, TOP \ 00194 __asm mov ebx, eax \ 00195 __asm dec ebx \ 00196 __asm and ebx, 7 \ 00197 __asm shl eax, 4 \ 00198 __asm shl ebx, 4 \ 00199 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00200 __asm fclex \ 00201 __asm fxtract \ 00202 __asm fnstsw new_sw \ 00203 __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ 00204 __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ 00205 } \ 00206 fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); \ 00207 FPU_PREP_PUSH(); 00208 #endif 00209 00210 // handles fadd,fmul,fsub,fsubr 00211 #ifdef WEAK_EXCEPTIONS 00212 #define FPUD_ARITH1(op) \ 00213 Bit16u save_cw; \ 00214 __asm { \ 00215 __asm fnstcw save_cw \ 00216 __asm mov eax, op1 \ 00217 __asm shl eax, 4 \ 00218 __asm fldcw fpu.cw_mask_all \ 00219 __asm mov ebx, op2 \ 00220 __asm shl ebx, 4 \ 00221 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00222 __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ 00223 __asm op st(1), st(0) \ 00224 __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ 00225 __asm fldcw save_cw \ 00226 } 00227 #else 00228 #define FPUD_ARITH1(op) \ 00229 Bit16u new_sw,save_cw; \ 00230 __asm { \ 00231 __asm fnstcw save_cw \ 00232 __asm fldcw fpu.cw_mask_all \ 00233 __asm mov eax, op1 \ 00234 __asm shl eax, 4 \ 00235 __asm mov ebx, op2 \ 00236 __asm shl ebx, 4 \ 00237 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00238 __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ 00239 __asm clx \ 00240 __asm op st(1), st(0) \ 00241 __asm fnstsw new_sw \ 00242 __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ 00243 __asm fldcw save_cw \ 00244 } \ 00245 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00246 #endif 00247 00248 // handles fadd,fmul,fsub,fsubr 00249 #ifdef WEAK_EXCEPTIONS 00250 #define FPUD_ARITH1_EA(op) \ 00251 Bit16u save_cw; \ 00252 __asm { \ 00253 __asm fnstcw save_cw \ 00254 __asm mov eax, op1 \ 00255 __asm fldcw fpu.cw_mask_all \ 00256 __asm shl eax, 4 \ 00257 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00258 __asm fxch \ 00259 __asm op st(1), st(0) \ 00260 __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ 00261 __asm fldcw save_cw \ 00262 } 00263 #else 00264 #define FPUD_ARITH1_EA(op) \ 00265 Bit16u new_sw,save_cw; \ 00266 __asm { \ 00267 __asm fnstcw save_cw \ 00268 __asm fldcw fpu.cw_mask_all \ 00269 __asm mov eax, op1 \ 00270 __asm shl eax, 4 \ 00271 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00272 __asm fxch \ 00273 __asm clx \ 00274 __asm op st(1), st(0) \ 00275 __asm fnstsw new_sw \ 00276 __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ 00277 __asm fldcw save_cw \ 00278 } \ 00279 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00280 #endif 00281 00282 // handles fsqrt,frndint 00283 #ifdef WEAK_EXCEPTIONS 00284 #define FPUD_ARITH2(op) \ 00285 Bit16u save_cw; \ 00286 __asm { \ 00287 __asm fnstcw save_cw \ 00288 __asm mov eax, TOP \ 00289 __asm fldcw fpu.cw_mask_all \ 00290 __asm shl eax, 4 \ 00291 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00292 __asm op \ 00293 __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ 00294 __asm fldcw save_cw \ 00295 } 00296 #else 00297 #define FPUD_ARITH2(op) \ 00298 Bit16u new_sw,save_cw; \ 00299 __asm { \ 00300 __asm fnstcw save_cw \ 00301 __asm fldcw fpu.cw_mask_all \ 00302 __asm mov eax, TOP \ 00303 __asm shl eax, 4 \ 00304 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00305 __asm clx \ 00306 __asm op \ 00307 __asm fnstsw new_sw \ 00308 __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ 00309 __asm fldcw save_cw \ 00310 } \ 00311 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00312 #endif 00313 00314 // handles fdiv,fdivr 00315 // (This is identical to FPUD_ARITH1 but without a WEAK_EXCEPTIONS variant) 00316 #define FPUD_ARITH3(op) \ 00317 Bit16u new_sw,save_cw; \ 00318 __asm { \ 00319 __asm fnstcw save_cw \ 00320 __asm fldcw fpu.cw_mask_all \ 00321 __asm mov eax, op1 \ 00322 __asm shl eax, 4 \ 00323 __asm mov ebx, op2 \ 00324 __asm shl ebx, 4 \ 00325 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00326 __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ 00327 __asm fclex \ 00328 __asm op st(1), st(0) \ 00329 __asm fnstsw new_sw \ 00330 __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ 00331 __asm fldcw save_cw \ 00332 } \ 00333 fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); 00334 00335 // handles fdiv,fdivr 00336 // (This is identical to FPUD_ARITH1_EA but without a WEAK_EXCEPTIONS variant) 00337 #define FPUD_ARITH3_EA(op) \ 00338 Bit16u new_sw,save_cw; \ 00339 __asm { \ 00340 __asm fnstcw save_cw \ 00341 __asm mov eax, op1 \ 00342 __asm fldcw fpu.cw_mask_all \ 00343 __asm shl eax, 4 \ 00344 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00345 __asm fxch \ 00346 __asm fclex \ 00347 __asm op st(1), st(0) \ 00348 __asm fnstsw new_sw \ 00349 __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ 00350 __asm fldcw save_cw \ 00351 } \ 00352 fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); 00353 00354 // handles fprem,fprem1,fscale 00355 #define FPUD_REMAINDER(op) \ 00356 Bit16u new_sw; \ 00357 __asm { \ 00358 __asm mov eax, TOP \ 00359 __asm mov ebx, eax \ 00360 __asm inc ebx \ 00361 __asm and ebx, 7 \ 00362 __asm shl ebx, 4 \ 00363 __asm shl eax, 4 \ 00364 __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ 00365 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00366 __asm fclex \ 00367 __asm op \ 00368 __asm fnstsw new_sw \ 00369 __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ 00370 __asm fstp st(0) \ 00371 } \ 00372 fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); 00373 00374 // handles fcom,fucom 00375 #define FPUD_COMPARE(op) \ 00376 Bit16u new_sw; \ 00377 __asm { \ 00378 __asm mov ebx, op2 \ 00379 __asm mov eax, op1 \ 00380 __asm shl ebx, 4 \ 00381 __asm shl eax, 4 \ 00382 __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ 00383 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00384 __asm clx \ 00385 __asm op \ 00386 __asm fnstsw new_sw \ 00387 } \ 00388 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00389 00390 #define FPUD_COMPARE_EA(op) \ 00391 Bit16u new_sw; \ 00392 __asm { \ 00393 __asm mov eax, op1 \ 00394 __asm shl eax, 4 \ 00395 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00396 __asm clx \ 00397 __asm op \ 00398 __asm fnstsw new_sw \ 00399 } \ 00400 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00401 00402 // handles fxam,ftst 00403 #define FPUD_EXAMINE(op) \ 00404 Bit16u new_sw; \ 00405 __asm { \ 00406 __asm mov eax, TOP \ 00407 __asm shl eax, 4 \ 00408 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00409 __asm clx \ 00410 __asm op \ 00411 __asm fnstsw new_sw \ 00412 __asm fstp st(0) \ 00413 } \ 00414 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00415 00416 // handles fpatan,fyl2xp1 00417 #ifdef WEAK_EXCEPTIONS 00418 #define FPUD_WITH_POP(op) \ 00419 __asm { \ 00420 __asm mov eax, TOP \ 00421 __asm mov ebx, eax \ 00422 __asm inc ebx \ 00423 __asm and ebx, 7 \ 00424 __asm shl ebx, 4 \ 00425 __asm shl eax, 4 \ 00426 __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ 00427 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00428 __asm op \ 00429 __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ 00430 } \ 00431 FPU_FPOP(); 00432 #else 00433 #define FPUD_WITH_POP(op) \ 00434 Bit16u new_sw; \ 00435 __asm { \ 00436 __asm mov eax, TOP \ 00437 __asm mov ebx, eax \ 00438 __asm inc ebx \ 00439 __asm and ebx, 7 \ 00440 __asm shl ebx, 4 \ 00441 __asm shl eax, 4 \ 00442 __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ 00443 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00444 __asm fclex \ 00445 __asm op \ 00446 __asm fnstsw new_sw \ 00447 __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ 00448 } \ 00449 fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); \ 00450 FPU_FPOP(); 00451 #endif 00452 00453 // handles fyl2x 00454 #ifdef WEAK_EXCEPTIONS 00455 #define FPUD_FYL2X(op) \ 00456 __asm { \ 00457 __asm mov eax, TOP \ 00458 __asm mov ebx, eax \ 00459 __asm inc ebx \ 00460 __asm and ebx, 7 \ 00461 __asm shl ebx, 4 \ 00462 __asm shl eax, 4 \ 00463 __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ 00464 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00465 __asm op \ 00466 __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ 00467 } \ 00468 FPU_FPOP(); 00469 #else 00470 #define FPUD_FYL2X(op) \ 00471 Bit16u new_sw; \ 00472 __asm { \ 00473 __asm mov eax, TOP \ 00474 __asm mov ebx, eax \ 00475 __asm inc ebx \ 00476 __asm and ebx, 7 \ 00477 __asm shl ebx, 4 \ 00478 __asm shl eax, 4 \ 00479 __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ 00480 __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ 00481 __asm fclex \ 00482 __asm op \ 00483 __asm fnstsw new_sw \ 00484 __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ 00485 } \ 00486 fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); \ 00487 FPU_FPOP(); 00488 #endif 00489 00490 // load math constants 00491 #define FPUD_LOAD_CONST(op) \ 00492 FPU_PREP_PUSH(); \ 00493 __asm { \ 00494 __asm mov eax, TOP \ 00495 __asm shl eax, 4 \ 00496 __asm clx \ 00497 __asm op \ 00498 __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ 00499 } \ 00500 00501 #else 00502 00503 // !defined _MSC_VER 00504 00505 #ifdef WEAK_EXCEPTIONS 00506 #define clx 00507 #else 00508 #define clx "fclex" 00509 #endif 00510 00511 #ifdef WEAK_EXCEPTIONS 00512 #define FPUD_LOAD(op,szI,szA) \ 00513 __asm__ volatile ( \ 00514 #op #szA " %1 \n" \ 00515 "fstpt %0 " \ 00516 : "=m" (fpu.p_regs[store_to]) \ 00517 : "m" (fpu.p_regs[8]) \ 00518 ); 00519 #else 00520 #define FPUD_LOAD(op,szI,szA) \ 00521 Bit16u new_sw; \ 00522 __asm__ volatile ( \ 00523 "fclex \n" \ 00524 #op #szA " %2 \n" \ 00525 "fnstsw %0 \n" \ 00526 "fstpt %1 " \ 00527 : "=&am" (new_sw), "=m" (fpu.p_regs[store_to]) \ 00528 : "m" (fpu.p_regs[8]) \ 00529 ); \ 00530 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00531 #endif 00532 00533 #ifdef WEAK_EXCEPTIONS 00534 #define FPUD_LOAD_EA(op,szI,szA) \ 00535 __asm__ volatile ( \ 00536 #op #szA " %0 \n" \ 00537 : \ 00538 : "m" (fpu.p_regs[8]) \ 00539 ); 00540 #else 00541 #define FPUD_LOAD_EA(op,szI,szA) \ 00542 Bit16u new_sw; \ 00543 __asm__ volatile ( \ 00544 "fclex \n" \ 00545 #op #szA " %1 \n" \ 00546 "fnstsw %0 \n" \ 00547 : "=&am" (new_sw) \ 00548 : "m" (fpu.p_regs[8]) \ 00549 : \ 00550 ); \ 00551 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00552 #endif 00553 00554 #ifdef WEAK_EXCEPTIONS 00555 #define FPUD_STORE(op,szI,szA) \ 00556 Bit16u save_cw; \ 00557 __asm__ volatile ( \ 00558 "fnstcw %0 \n" \ 00559 "fldcw %3 \n" \ 00560 "fldt %2 \n" \ 00561 #op #szA " %1 \n" \ 00562 "fldcw %0 " \ 00563 : "=m" (save_cw), "=m" (fpu.p_regs[8]) \ 00564 : "m" (fpu.p_regs[TOP]), "m" (fpu.cw_mask_all) \ 00565 ); 00566 #else 00567 #define FPUD_STORE(op,szI,szA) \ 00568 Bit16u new_sw,save_cw; \ 00569 __asm__ volatile ( \ 00570 "fnstcw %1 \n" \ 00571 "fldcw %4 \n" \ 00572 "fldt %3 \n" \ 00573 "fclex \n" \ 00574 #op #szA " %2 \n" \ 00575 "fnstsw %0 \n" \ 00576 "fldcw %1 " \ 00577 : "=&am" (new_sw), "=m" (save_cw), "=m" (fpu.p_regs[8]) \ 00578 : "m" (fpu.p_regs[TOP]), "m" (fpu.cw_mask_all) \ 00579 ); \ 00580 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00581 #endif 00582 00583 // handles fsin,fcos,f2xm1,fchs,fabs 00584 #define FPUD_TRIG(op) \ 00585 Bit16u new_sw; \ 00586 __asm__ volatile ( \ 00587 "fldt %1 \n" \ 00588 clx" \n" \ 00589 #op" \n" \ 00590 "fnstsw %0 \n" \ 00591 "fstpt %1 " \ 00592 : "=&am" (new_sw), "+m" (fpu.p_regs[TOP]) \ 00593 ); \ 00594 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00595 00596 // handles fsincos 00597 #define FPUD_SINCOS() \ 00598 Bit16u new_sw; \ 00599 __asm__ volatile ( \ 00600 "fldt %1 \n" \ 00601 clx" \n" \ 00602 "fsincos \n" \ 00603 "fnstsw %0 \n" \ 00604 "fstpt %2 \n" \ 00605 "movw %0, %%ax \n" \ 00606 "sahf \n" \ 00607 "jp 1f \n" \ 00608 "fstpt %1 \n" \ 00609 "1: " \ 00610 : "=m" (new_sw), "+m" (fpu.p_regs[TOP]), \ 00611 "=m" (fpu.p_regs[(TOP-1)&7]) \ 00612 : \ 00613 : "ax", "cc" \ 00614 ); \ 00615 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); \ 00616 if ((new_sw&0x0400)==0) FPU_PREP_PUSH(); 00617 00618 // handles fptan 00619 #define FPUD_PTAN() \ 00620 Bit16u new_sw; \ 00621 __asm__ volatile ( \ 00622 "fldt %1 \n" \ 00623 clx" \n" \ 00624 "fptan \n" \ 00625 "fnstsw %0 \n" \ 00626 "fstpt %2 \n" \ 00627 "movw %0, %%ax \n" \ 00628 "sahf \n" \ 00629 "jp 1f \n" \ 00630 "fstpt %1 \n" \ 00631 "1: " \ 00632 : "=m" (new_sw), "+m" (fpu.p_regs[TOP]), \ 00633 "=m" (fpu.p_regs[(TOP-1)&7]) \ 00634 : \ 00635 : "ax", "cc" \ 00636 ); \ 00637 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); \ 00638 if ((new_sw&0x0400)==0) FPU_PREP_PUSH(); 00639 00640 // handles fxtract 00641 #ifdef WEAK_EXCEPTIONS 00642 #define FPUD_XTRACT \ 00643 __asm__ volatile ( \ 00644 "fldt %0 \n" \ 00645 "fxtract \n" \ 00646 "fstpt %1 \n" \ 00647 "fstpt %0 " \ 00648 : "+m" (fpu.p_regs[TOP]), "=m" (fpu.p_regs[(TOP-1)&7]) \ 00649 ); \ 00650 FPU_PREP_PUSH(); 00651 #else 00652 #define FPUD_XTRACT \ 00653 Bit16u new_sw; \ 00654 __asm__ volatile ( \ 00655 "fldt %1 \n" \ 00656 "fclex \n" \ 00657 "fxtract \n" \ 00658 "fnstsw %0 \n" \ 00659 "fstpt %2 \n" \ 00660 "fstpt %1 " \ 00661 : "=&am" (new_sw), "+m" (fpu.p_regs[TOP]), \ 00662 "=m" (fpu.p_regs[(TOP-1)&7]) \ 00663 ); \ 00664 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); \ 00665 FPU_PREP_PUSH(); 00666 #endif 00667 00668 // handles fadd,fmul,fsub,fsubr 00669 #ifdef WEAK_EXCEPTIONS 00670 #define FPUD_ARITH1(op) \ 00671 Bit16u save_cw; \ 00672 __asm__ volatile ( \ 00673 "fnstcw %0 \n" \ 00674 "fldcw %3 \n" \ 00675 "fldt %2 \n" \ 00676 "fldt %1 \n" \ 00677 #op" \n" \ 00678 "fstpt %1 \n" \ 00679 "fldcw %0 " \ 00680 : "=m" (save_cw), "+m" (fpu.p_regs[op1]) \ 00681 : "m" (fpu.p_regs[op2]), "m" (fpu.cw_mask_all) \ 00682 ); 00683 #else 00684 #define FPUD_ARITH1(op) \ 00685 Bit16u new_sw,save_cw; \ 00686 __asm__ volatile ( \ 00687 "fnstcw %1 \n" \ 00688 "fldcw %4 \n" \ 00689 "fldt %3 \n" \ 00690 "fldt %2 \n" \ 00691 "fclex \n" \ 00692 #op" \n" \ 00693 "fnstsw %0 \n" \ 00694 "fstpt %2 \n" \ 00695 "fldcw %1 " \ 00696 : "=&am" (new_sw), "=m" (save_cw), "+m" (fpu.p_regs[op1]) \ 00697 : "m" (fpu.p_regs[op2]), "m" (fpu.cw_mask_all) \ 00698 ); \ 00699 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00700 #endif 00701 00702 // handles fadd,fmul,fsub,fsubr 00703 #ifdef WEAK_EXCEPTIONS 00704 #define FPUD_ARITH1_EA(op) \ 00705 Bit16u save_cw; \ 00706 __asm__ volatile ( \ 00707 "fnstcw %0 \n" \ 00708 "fldcw %2 \n" \ 00709 "fldt %1 \n" \ 00710 #op" \n" \ 00711 "fstpt %1 \n" \ 00712 "fldcw %0 " \ 00713 : "=m" (save_cw), "+m" (fpu.p_regs[op1]) \ 00714 : "m" (fpu.cw_mask_all) \ 00715 ); 00716 #else 00717 #define FPUD_ARITH1_EA(op) \ 00718 Bit16u new_sw,save_cw; \ 00719 __asm__ volatile ( \ 00720 "fnstcw %1 \n" \ 00721 "fldcw %3 \n" \ 00722 "fldt %2 \n" \ 00723 "fclex \n" \ 00724 #op" \n" \ 00725 "fnstsw %0 \n" \ 00726 "fstpt %2 \n" \ 00727 "fldcw %1 " \ 00728 : "=&am" (new_sw), "=m" (save_cw), "+m" (fpu.p_regs[op1]) \ 00729 : "m" (fpu.cw_mask_all) \ 00730 ); \ 00731 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00732 #endif 00733 00734 // handles fsqrt,frndint 00735 #ifdef WEAK_EXCEPTIONS 00736 #define FPUD_ARITH2(op) \ 00737 Bit16u save_cw; \ 00738 __asm__ volatile ( \ 00739 "fnstcw %0 \n" \ 00740 "fldcw %2 \n" \ 00741 "fldt %1 \n" \ 00742 #op" \n" \ 00743 "fstpt %1 \n" \ 00744 "fldcw %0 " \ 00745 : "=m" (save_cw), "+m" (fpu.p_regs[TOP]) \ 00746 : "m" (fpu.cw_mask_all) \ 00747 ); 00748 #else 00749 #define FPUD_ARITH2(op) \ 00750 Bit16u new_sw,save_cw; \ 00751 __asm__ volatile ( \ 00752 "fnstcw %1 \n" \ 00753 "fldcw %3 \n" \ 00754 "fldt %2 \n" \ 00755 "fclex \n" \ 00756 #op" \n" \ 00757 "fnstsw %0 \n" \ 00758 "fstpt %2 \n" \ 00759 "fldcw %1 " \ 00760 : "=&am" (new_sw), "=m" (save_cw), "+m" (fpu.p_regs[TOP]) \ 00761 : "m" (fpu.cw_mask_all) \ 00762 ); \ 00763 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00764 #endif 00765 00766 // handles fdiv,fdivr 00767 // (This is identical to FPUD_ARITH1 but without a WEAK_EXCEPTIONS variant) 00768 #define FPUD_ARITH3(op) \ 00769 Bit16u new_sw,save_cw; \ 00770 __asm__ volatile ( \ 00771 "fnstcw %1 \n" \ 00772 "fldcw %4 \n" \ 00773 "fldt %3 \n" \ 00774 "fldt %2 \n" \ 00775 "fclex \n" \ 00776 #op" \n" \ 00777 "fnstsw %0 \n" \ 00778 "fstpt %2 \n" \ 00779 "fldcw %1 " \ 00780 : "=&am" (new_sw), "=m" (save_cw), "+m" (fpu.p_regs[op1]) \ 00781 : "m" (fpu.p_regs[op2]), "m" (fpu.cw_mask_all) \ 00782 ); \ 00783 fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); 00784 00785 // handles fdiv,fdivr 00786 // (This is identical to FPUD_ARITH1_EA but without a WEAK_EXCEPTIONS variant) 00787 #define FPUD_ARITH3_EA(op) \ 00788 Bit16u new_sw,save_cw; \ 00789 __asm__ volatile ( \ 00790 "fnstcw %1 \n" \ 00791 "fldcw %3 \n" \ 00792 "fldt %2 \n" \ 00793 "fclex \n" \ 00794 #op" \n" \ 00795 "fnstsw %0 \n" \ 00796 "fstpt %2 \n" \ 00797 "fldcw %1 " \ 00798 : "=&am" (new_sw), "=m" (save_cw), "+m" (fpu.p_regs[op1]) \ 00799 : "m" (fpu.cw_mask_all) \ 00800 ); \ 00801 fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); 00802 00803 // handles fprem,fprem1,fscale 00804 #define FPUD_REMAINDER(op) \ 00805 Bit16u new_sw; \ 00806 __asm__ volatile ( \ 00807 "fldt %2 \n" \ 00808 "fldt %1 \n" \ 00809 "fclex \n" \ 00810 #op" \n" \ 00811 "fnstsw %0 \n" \ 00812 "fstpt %1 \n" \ 00813 "fstp %%st(0) " \ 00814 : "=&am" (new_sw), "+m" (fpu.p_regs[TOP]) \ 00815 : "m" (fpu.p_regs[(TOP+1)&7]) \ 00816 ); \ 00817 fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); 00818 00819 // handles fcom,fucom 00820 #define FPUD_COMPARE(op) \ 00821 Bit16u new_sw; \ 00822 __asm__ volatile ( \ 00823 "fldt %2 \n" \ 00824 "fldt %1 \n" \ 00825 clx" \n" \ 00826 #op" \n" \ 00827 "fnstsw %0 " \ 00828 : "=&am" (new_sw) \ 00829 : "m" (fpu.p_regs[op1]), "m" (fpu.p_regs[op2]) \ 00830 ); \ 00831 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00832 00833 // handles fcom,fucom 00834 #define FPUD_COMPARE_EA(op) \ 00835 Bit16u new_sw; \ 00836 __asm__ volatile ( \ 00837 "fldt %1 \n" \ 00838 clx" \n" \ 00839 #op" \n" \ 00840 "fnstsw %0 " \ 00841 : "=&am" (new_sw) \ 00842 : "m" (fpu.p_regs[op1]) \ 00843 ); \ 00844 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00845 00846 // handles fxam,ftst 00847 #define FPUD_EXAMINE(op) \ 00848 Bit16u new_sw; \ 00849 __asm__ volatile ( \ 00850 "fldt %1 \n" \ 00851 clx" \n" \ 00852 #op" \n" \ 00853 "fnstsw %0 \n" \ 00854 "fstp %%st(0) " \ 00855 : "=&am" (new_sw) \ 00856 : "m" (fpu.p_regs[TOP]) \ 00857 ); \ 00858 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); 00859 00860 // handles fpatan,fyl2xp1 00861 #ifdef WEAK_EXCEPTIONS 00862 #define FPUD_WITH_POP(op) \ 00863 __asm__ volatile ( \ 00864 "fldt %0 \n" \ 00865 "fldt %1 \n" \ 00866 #op" \n" \ 00867 "fstpt %0 \n" \ 00868 : "+m" (fpu.p_regs[(TOP+1)&7]) \ 00869 : "m" (fpu.p_regs[TOP]) \ 00870 ); \ 00871 FPU_FPOP(); 00872 #else 00873 #define FPUD_WITH_POP(op) \ 00874 Bit16u new_sw; \ 00875 __asm__ volatile ( \ 00876 "fldt %1 \n" \ 00877 "fldt %2 \n" \ 00878 "fclex \n" \ 00879 #op" \n" \ 00880 "fnstsw %0 \n" \ 00881 "fstpt %1 \n" \ 00882 : "=&am" (new_sw), "+m" (fpu.p_regs[(TOP+1)&7]) \ 00883 : "m" (fpu.p_regs[TOP]) \ 00884 ); \ 00885 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); \ 00886 FPU_FPOP(); 00887 #endif 00888 00889 // handles fyl2x 00890 #ifdef WEAK_EXCEPTIONS 00891 #define FPUD_FYL2X(op) \ 00892 __asm__ volatile ( \ 00893 "fldt %0 \n" \ 00894 "fldt %1 \n" \ 00895 #op" \n" \ 00896 "fstpt %0 \n" \ 00897 : "+m" (fpu.p_regs[(TOP+1)&7]) \ 00898 : "m" (fpu.p_regs[TOP]) \ 00899 ); \ 00900 FPU_FPOP(); 00901 #else 00902 #define FPUD_FYL2X(op) \ 00903 Bit16u new_sw; \ 00904 __asm__ volatile ( \ 00905 "fldt %1 \n" \ 00906 "fldt %2 \n" \ 00907 "fclex \n" \ 00908 #op" \n" \ 00909 "fnstsw %0 \n" \ 00910 "fstpt %1 \n" \ 00911 : "=&am" (new_sw), "+m" (fpu.p_regs[(TOP+1)&7]) \ 00912 : "m" (fpu.p_regs[TOP]) \ 00913 ); \ 00914 fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); \ 00915 FPU_FPOP(); 00916 #endif 00917 00918 // load math constants 00919 #define FPUD_LOAD_CONST(op) \ 00920 FPU_PREP_PUSH(); \ 00921 __asm__ volatile ( \ 00922 clx" \n" \ 00923 #op" \n" \ 00924 "fstpt %0 \n" \ 00925 : "=m" (fpu.p_regs[TOP]) \ 00926 ); 00927 00928 #endif 00929 00930 #ifdef WEAK_EXCEPTIONS 00931 const Bit16u exc_mask=0x7f00; 00932 #else 00933 const Bit16u exc_mask=0xffbf; 00934 #endif 00935 00936 static void FPU_FINIT(void) { 00937 FPU_SetCW(0x37F); 00938 fpu.sw=0; 00939 TOP=FPU_GET_TOP(); 00940 fpu.tags[0]=TAG_Empty; 00941 fpu.tags[1]=TAG_Empty; 00942 fpu.tags[2]=TAG_Empty; 00943 fpu.tags[3]=TAG_Empty; 00944 fpu.tags[4]=TAG_Empty; 00945 fpu.tags[5]=TAG_Empty; 00946 fpu.tags[6]=TAG_Empty; 00947 fpu.tags[7]=TAG_Empty; 00948 fpu.tags[8]=TAG_Valid; // is only used by us 00949 } 00950 00951 static void FPU_FCLEX(void){ 00952 fpu.sw&=0x7f00; //should clear exceptions 00953 } 00954 00955 static void FPU_FNOP(void){ 00956 } 00957 00958 static void FPU_PREP_PUSH(void){ 00959 TOP = (TOP - 1) &7; 00960 // if (GCC_UNLIKELY(fpu.tags[TOP] != TAG_Empty)) E_Exit("FPU stack overflow"); 00961 fpu.tags[TOP] = TAG_Valid; 00962 } 00963 00964 static void FPU_FPOP(void){ 00965 // if (GCC_UNLIKELY(fpu.tags[TOP] == TAG_Empty)) E_Exit("FPU stack underflow"); 00966 fpu.tags[TOP] = TAG_Empty; 00967 TOP = ((TOP+1)&7); 00968 } 00969 00970 static void FPU_FLD_F32(PhysPt addr,Bitu store_to) { 00971 fpu.p_regs[8].m1 = mem_readd(addr); 00972 FPUD_LOAD(fld,DWORD,s) 00973 } 00974 00975 static void FPU_FLD_F32_EA(PhysPt addr) { 00976 fpu.p_regs[8].m1 = mem_readd(addr); 00977 FPUD_LOAD_EA(fld,DWORD,s) 00978 } 00979 00980 static void FPU_FLD_F64(PhysPt addr,Bitu store_to) { 00981 fpu.p_regs[8].m1 = mem_readd(addr); 00982 fpu.p_regs[8].m2 = mem_readd(addr+4); 00983 FPUD_LOAD(fld,QWORD,l) 00984 } 00985 00986 static void FPU_FLD_F64_EA(PhysPt addr) { 00987 fpu.p_regs[8].m1 = mem_readd(addr); 00988 fpu.p_regs[8].m2 = mem_readd(addr+4); 00989 FPUD_LOAD_EA(fld,QWORD,l) 00990 } 00991 00992 static void FPU_FLD_F80(PhysPt addr) { 00993 fpu.p_regs[TOP].m1 = mem_readd(addr); 00994 fpu.p_regs[TOP].m2 = mem_readd(addr+4); 00995 fpu.p_regs[TOP].m3 = mem_readw(addr+8); 00996 FPU_SET_C1(0); 00997 } 00998 00999 static void FPU_FLD_I16(PhysPt addr,Bitu store_to) { 01000 fpu.p_regs[8].m1 = (Bit32u)mem_readw(addr); 01001 FPUD_LOAD(fild,WORD,s) 01002 } 01003 01004 static void FPU_FLD_I16_EA(PhysPt addr) { 01005 fpu.p_regs[8].m1 = (Bit32u)mem_readw(addr); 01006 FPUD_LOAD_EA(fild,WORD,s) 01007 } 01008 01009 static void FPU_FLD_I32(PhysPt addr,Bitu store_to) { 01010 fpu.p_regs[8].m1 = mem_readd(addr); 01011 FPUD_LOAD(fild,DWORD,l) 01012 } 01013 01014 static void FPU_FLD_I32_EA(PhysPt addr) { 01015 fpu.p_regs[8].m1 = mem_readd(addr); 01016 FPUD_LOAD_EA(fild,DWORD,l) 01017 } 01018 01019 static void FPU_FLD_I64(PhysPt addr,Bitu store_to) { 01020 fpu.p_regs[8].m1 = mem_readd(addr); 01021 fpu.p_regs[8].m2 = mem_readd(addr+4); 01022 FPUD_LOAD(fild,QWORD,q) 01023 } 01024 01025 static void FPU_FBLD(PhysPt addr,Bitu store_to) { 01026 fpu.p_regs[8].m1 = mem_readd(addr); 01027 fpu.p_regs[8].m2 = mem_readd(addr+4); 01028 fpu.p_regs[8].m3 = mem_readw(addr+8); 01029 FPUD_LOAD(fbld,TBYTE,) 01030 } 01031 01032 static void FPU_FST_F32(PhysPt addr) { 01033 FPUD_STORE(fstp,DWORD,s) 01034 mem_writed(addr,fpu.p_regs[8].m1); 01035 } 01036 01037 static void FPU_FST_F64(PhysPt addr) { 01038 FPUD_STORE(fstp,QWORD,l) 01039 mem_writed(addr,fpu.p_regs[8].m1); 01040 mem_writed(addr+4,fpu.p_regs[8].m2); 01041 } 01042 01043 static void FPU_FST_F80(PhysPt addr) { 01044 mem_writed(addr,fpu.p_regs[TOP].m1); 01045 mem_writed(addr+4,fpu.p_regs[TOP].m2); 01046 mem_writew(addr+8,fpu.p_regs[TOP].m3); 01047 FPU_SET_C1(0); 01048 } 01049 01050 static void FPU_FST_I16(PhysPt addr) { 01051 FPUD_STORE(fistp,WORD,s) 01052 mem_writew(addr,(Bit16u)fpu.p_regs[8].m1); 01053 } 01054 01055 static void FPU_FST_I32(PhysPt addr) { 01056 FPUD_STORE(fistp,DWORD,l) 01057 mem_writed(addr,fpu.p_regs[8].m1); 01058 } 01059 01060 static void FPU_FST_I64(PhysPt addr) { 01061 FPUD_STORE(fistp,QWORD,q) 01062 mem_writed(addr,fpu.p_regs[8].m1); 01063 mem_writed(addr+4,fpu.p_regs[8].m2); 01064 } 01065 01066 static void FPU_FBST(PhysPt addr) { 01067 FPUD_STORE(fbstp,TBYTE,) 01068 mem_writed(addr,fpu.p_regs[8].m1); 01069 mem_writed(addr+4,fpu.p_regs[8].m2); 01070 mem_writew(addr+8,fpu.p_regs[8].m3); 01071 } 01072 01073 01074 static void FPU_FSIN(void){ 01075 FPUD_TRIG(fsin) 01076 } 01077 01078 static void FPU_FSINCOS(void){ 01079 FPUD_SINCOS() 01080 } 01081 01082 static void FPU_FCOS(void){ 01083 FPUD_TRIG(fcos) 01084 } 01085 01086 static void FPU_FSQRT(void){ 01087 FPUD_ARITH2(fsqrt) 01088 } 01089 01090 static void FPU_FPATAN(void){ 01091 FPUD_WITH_POP(fpatan) 01092 } 01093 01094 static void FPU_FPTAN(void){ 01095 FPUD_PTAN() 01096 } 01097 01098 01099 static void FPU_FADD(Bitu op1, Bitu op2){ 01100 FPUD_ARITH1(faddp) 01101 } 01102 01103 static void FPU_FADD_EA(Bitu op1){ 01104 FPUD_ARITH1_EA(faddp) 01105 } 01106 01107 static void FPU_FDIV(Bitu op1, Bitu op2){ 01108 FPUD_ARITH3(fdivp) 01109 } 01110 01111 static void FPU_FDIV_EA(Bitu op1){ 01112 FPUD_ARITH3_EA(fdivp) 01113 } 01114 01115 static void FPU_FDIVR(Bitu op1, Bitu op2){ 01116 FPUD_ARITH3(fdivrp) 01117 } 01118 01119 static void FPU_FDIVR_EA(Bitu op1){ 01120 FPUD_ARITH3_EA(fdivrp) 01121 } 01122 01123 static void FPU_FMUL(Bitu op1, Bitu op2){ 01124 FPUD_ARITH1(fmulp) 01125 } 01126 01127 static void FPU_FMUL_EA(Bitu op1){ 01128 FPUD_ARITH1_EA(fmulp) 01129 } 01130 01131 static void FPU_FSUB(Bitu op1, Bitu op2){ 01132 FPUD_ARITH1(fsubp) 01133 } 01134 01135 static void FPU_FSUB_EA(Bitu op1){ 01136 FPUD_ARITH1_EA(fsubp) 01137 } 01138 01139 static void FPU_FSUBR(Bitu op1, Bitu op2){ 01140 FPUD_ARITH1(fsubrp) 01141 } 01142 01143 static void FPU_FSUBR_EA(Bitu op1){ 01144 FPUD_ARITH1_EA(fsubrp) 01145 } 01146 01147 static void FPU_FXCH(Bitu stv, Bitu other){ 01148 FPU_Tag tag = fpu.tags[other]; 01149 fpu.tags[other] = fpu.tags[stv]; 01150 fpu.tags[stv] = tag; 01151 01152 Bit32u m1s = fpu.p_regs[other].m1; 01153 Bit32u m2s = fpu.p_regs[other].m2; 01154 Bit16u m3s = fpu.p_regs[other].m3; 01155 fpu.p_regs[other].m1 = fpu.p_regs[stv].m1; 01156 fpu.p_regs[other].m2 = fpu.p_regs[stv].m2; 01157 fpu.p_regs[other].m3 = fpu.p_regs[stv].m3; 01158 fpu.p_regs[stv].m1 = m1s; 01159 fpu.p_regs[stv].m2 = m2s; 01160 fpu.p_regs[stv].m3 = m3s; 01161 01162 FPU_SET_C1(0); 01163 } 01164 01165 static void FPU_FST(Bitu stv, Bitu other){ 01166 fpu.tags[other] = fpu.tags[stv]; 01167 01168 fpu.p_regs[other].m1 = fpu.p_regs[stv].m1; 01169 fpu.p_regs[other].m2 = fpu.p_regs[stv].m2; 01170 fpu.p_regs[other].m3 = fpu.p_regs[stv].m3; 01171 01172 FPU_SET_C1(0); 01173 } 01174 01175 static inline void FPU_FCMOV(Bitu st, Bitu other){ 01176 fpu.p_regs[st] = fpu.p_regs[other]; 01177 fpu.tags[st] = fpu.tags[other]; 01178 } 01179 01180 static void FPU_FCOM(Bitu op1, Bitu op2){ 01181 FPUD_COMPARE(fcompp) 01182 } 01183 01184 static void FPU_FUCOMI(Bitu st, Bitu other){ 01185 LOG_MSG("FPU WARNING: FPU_FUCOMI called, needs testing"); 01186 01187 FPU_FCOM(st,other); 01188 01189 Bitu FillFlags(void);//Why is this needed for VS2015? 01190 01191 FillFlags(); 01192 SETFLAGBIT(OF,false); 01193 01194 if (fpu.sw & (1u << 14u)/*C3*/) {//if(fpu.regs[st].d == fpu.regs[other].d){ 01195 SETFLAGBIT(ZF,true);SETFLAGBIT(PF,false);SETFLAGBIT(CF,false);return; 01196 } 01197 else if (fpu.sw & (1u << 8u)/*C0*/) {//if(fpu.regs[st].d < fpu.regs[other].d){ 01198 SETFLAGBIT(ZF,false);SETFLAGBIT(PF,false);SETFLAGBIT(CF,true);return; 01199 } 01200 // st > other 01201 SETFLAGBIT(ZF,false);SETFLAGBIT(PF,false);SETFLAGBIT(CF,false);return; 01202 } 01203 01204 static inline void FPU_FCOMI(Bitu st, Bitu other){ 01205 FPU_FUCOMI(st,other); 01206 01207 if(((fpu.tags[st] != TAG_Valid) && (fpu.tags[st] != TAG_Zero)) || 01208 ((fpu.tags[other] != TAG_Valid) && (fpu.tags[other] != TAG_Zero))){ 01209 SETFLAGBIT(ZF,true);SETFLAGBIT(PF,true);SETFLAGBIT(CF,true);return; 01210 } 01211 01212 } 01213 01214 static void FPU_FCOM_EA(Bitu op1){ 01215 FPUD_COMPARE_EA(fcompp) 01216 } 01217 01218 static void FPU_FUCOM(Bitu op1, Bitu op2){ 01219 FPUD_COMPARE(fucompp) 01220 } 01221 01222 static void FPU_FRNDINT(void){ 01223 FPUD_ARITH2(frndint) 01224 } 01225 01226 static void FPU_FPREM(void){ 01227 FPUD_REMAINDER(fprem) 01228 } 01229 01230 static void FPU_FPREM1(void){ 01231 FPUD_REMAINDER(fprem1) 01232 } 01233 01234 static void FPU_FXAM(void){ 01235 FPUD_EXAMINE(fxam) 01236 // handle empty registers (C1 set to sign in any way!) 01237 if(fpu.tags[TOP] == TAG_Empty) { 01238 FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(1); 01239 return; 01240 } 01241 } 01242 01243 static void FPU_F2XM1(void){ 01244 FPUD_TRIG(f2xm1) 01245 } 01246 01247 static void FPU_FYL2X(void){ 01248 FPUD_FYL2X(fyl2x) 01249 } 01250 01251 static void FPU_FYL2XP1(void){ 01252 FPUD_WITH_POP(fyl2xp1) 01253 } 01254 01255 static void FPU_FSCALE(void){ 01256 FPUD_REMAINDER(fscale) 01257 } 01258 01259 01260 static void FPU_FSTENV(PhysPt addr){ 01261 FPU_SET_TOP(TOP); 01262 if(!cpu.code.big) { 01263 mem_writew(addr+0,static_cast<Bit16u>(fpu.cw)); 01264 mem_writew(addr+2,static_cast<Bit16u>(fpu.sw)); 01265 mem_writew(addr+4,static_cast<Bit16u>(FPU_GetTag())); 01266 } else { 01267 mem_writed(addr+0,static_cast<Bit32u>(fpu.cw)); 01268 mem_writed(addr+4,static_cast<Bit32u>(fpu.sw)); 01269 mem_writed(addr+8,static_cast<Bit32u>(FPU_GetTag())); 01270 } 01271 } 01272 01273 static void FPU_FLDENV(PhysPt addr){ 01274 Bit16u tag; 01275 Bitu cw; 01276 if(!cpu.code.big) { 01277 cw = mem_readw(addr+0); 01278 fpu.sw = mem_readw(addr+2); 01279 tag = mem_readw(addr+4); 01280 } else { 01281 cw = mem_readd(addr+0); 01282 fpu.sw = (Bit16u)mem_readd(addr+4); 01283 Bit32u tagbig = mem_readd(addr+8); 01284 tag = static_cast<Bit16u>(tagbig); 01285 } 01286 FPU_SetTag(tag); 01287 FPU_SetCW(cw); 01288 TOP=FPU_GET_TOP(); 01289 } 01290 01291 static void FPU_FSAVE(PhysPt addr){ 01292 FPU_FSTENV(addr); 01293 Bitu start=(cpu.code.big?28:14); 01294 for(Bitu i=0;i<8;i++){ 01295 mem_writed(addr+start,fpu.p_regs[STV(i)].m1); 01296 mem_writed(addr+start+4,fpu.p_regs[STV(i)].m2); 01297 mem_writew(addr+start+8,fpu.p_regs[STV(i)].m3); 01298 start+=10; 01299 } 01300 FPU_FINIT(); 01301 } 01302 01303 static void FPU_FRSTOR(PhysPt addr){ 01304 FPU_FLDENV(addr); 01305 Bitu start=(cpu.code.big?28:14); 01306 for(Bitu i=0;i<8;i++){ 01307 fpu.p_regs[STV(i)].m1 = mem_readd(addr+start); 01308 fpu.p_regs[STV(i)].m2 = mem_readd(addr+start+4); 01309 fpu.p_regs[STV(i)].m3 = mem_readw(addr+start+8); 01310 start+=10; 01311 } 01312 } 01313 01314 01315 static void FPU_FXTRACT(void) { 01316 FPUD_XTRACT 01317 } 01318 01319 static void FPU_FCHS(void){ 01320 FPUD_TRIG(fchs) 01321 } 01322 01323 static void FPU_FABS(void){ 01324 FPUD_TRIG(fabs) 01325 } 01326 01327 static void FPU_FTST(void){ 01328 FPUD_EXAMINE(ftst) 01329 } 01330 01331 static void FPU_FLD1(void){ 01332 FPUD_LOAD_CONST(fld1) 01333 } 01334 01335 static void FPU_FLDL2T(void){ 01336 FPUD_LOAD_CONST(fldl2t) 01337 } 01338 01339 static void FPU_FLDL2E(void){ 01340 FPUD_LOAD_CONST(fldl2e) 01341 } 01342 01343 static void FPU_FLDPI(void){ 01344 FPUD_LOAD_CONST(fldpi) 01345 } 01346 01347 static void FPU_FLDLG2(void){ 01348 FPUD_LOAD_CONST(fldlg2) 01349 } 01350 01351 static void FPU_FLDLN2(void){ 01352 FPUD_LOAD_CONST(fldln2) 01353 } 01354 01355 static void FPU_FLDZ(void){ 01356 FPUD_LOAD_CONST(fldz) 01357 fpu.tags[TOP]=TAG_Zero; 01358 }