DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/fpu/fpu_instructions_x86.h
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 }