DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/cpu/core_dyn_x86/dyn_fpu.h
00001 /*
00002  *  Copyright (C) 2002-2013  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
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 
00020 #include "dosbox.h"
00021 #if C_FPU
00022 
00023 #include <math.h>
00024 #include <float.h>
00025 #include "cross.h"
00026 #include "mem.h"
00027 #include "fpu.h"
00028 #include "cpu.h"
00029 
00030 
00031 static void FPU_FDECSTP(){
00032         TOP = (TOP - 1) & 7;
00033 }
00034 
00035 static void FPU_FINCSTP(){
00036         TOP = (TOP + 1) & 7;
00037 }
00038 
00039 static void FPU_FNSTCW(PhysPt addr){
00040         mem_writew(addr,fpu.cw);
00041 }
00042 
00043 static void FPU_FFREE(Bitu st) {
00044         fpu.tags[st]=TAG_Empty;
00045 }
00046 
00047 
00048 #if C_FPU_X86
00049 #include "../../fpu/fpu_instructions_x86.h"
00050 #else
00051 #include "../../fpu/fpu_instructions.h"
00052 #endif
00053 
00054 
00055 #define dyn_fpu_top() {                         \
00056         gen_protectflags();                             \
00057         gen_load_host(&TOP,DREG(EA),4); \
00058         gen_dop_word_imm(DOP_ADD,true,DREG(EA),decode.modrm.rm);        \
00059         gen_dop_word_imm(DOP_AND,true,DREG(EA),7);      \
00060         gen_load_host(&TOP,DREG(TMPB),4);                       \
00061 }
00062 
00063 static void dyn_eatree() {
00064         Bitu group=(decode.modrm.val >> 3) & 7;
00065         switch (group){
00066         case 0x00:              /* FADD ST,STi */
00067                 gen_call_function((void*)&FPU_FADD_EA,"%Ddr",DREG(TMPB));
00068                 break;
00069         case 0x01:              /* FMUL  ST,STi */
00070                 gen_call_function((void*)&FPU_FMUL_EA,"%Ddr",DREG(TMPB));
00071                 break;
00072         case 0x02:              /* FCOM  STi */
00073                 gen_call_function((void*)&FPU_FCOM_EA,"%Ddr",DREG(TMPB));
00074                 break;
00075         case 0x03:              /* FCOMP STi */
00076                 gen_call_function((void*)&FPU_FCOM_EA,"%Ddr",DREG(TMPB));
00077                 gen_call_function((void*)&FPU_FPOP,"");
00078                 break;
00079         case 0x04:              /* FSUB  ST,STi */
00080                 gen_call_function((void*)&FPU_FSUB_EA,"%Ddr",DREG(TMPB));
00081                 break;  
00082         case 0x05:              /* FSUBR ST,STi */
00083                 gen_call_function((void*)&FPU_FSUBR_EA,"%Ddr",DREG(TMPB));
00084                 break;
00085         case 0x06:              /* FDIV  ST,STi */
00086                 gen_call_function((void*)&FPU_FDIV_EA,"%Ddr",DREG(TMPB));
00087                 break;
00088         case 0x07:              /* FDIVR ST,STi */
00089                 gen_call_function((void*)&FPU_FDIVR_EA,"%Ddr",DREG(TMPB));
00090                 break;
00091         default:
00092                 break;
00093         }
00094 }
00095 
00096 static void dyn_fpu_esc0(){
00097         dyn_get_modrm(); 
00098         if (decode.modrm.val >= 0xc0) { 
00099                 dyn_fpu_top();
00100                 Bitu group=(decode.modrm.val >> 3) & 7;
00101                 switch (group){
00102                 case 0x00:              //FADD ST,STi /
00103                         gen_call_function((void*)&FPU_FADD,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00104                         break;
00105                 case 0x01:              // FMUL  ST,STi /
00106                         gen_call_function((void*)&FPU_FMUL,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00107                         break;
00108                 case 0x02:              // FCOM  STi /
00109                         gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00110                         break;
00111                 case 0x03:              // FCOMP STi /
00112                         gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00113                         gen_call_function((void*)&FPU_FPOP,"");
00114                         break;
00115                 case 0x04:              // FSUB  ST,STi /
00116                         gen_call_function((void*)&FPU_FSUB,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00117                         break;  
00118                 case 0x05:              // FSUBR ST,STi /
00119                         gen_call_function((void*)&FPU_FSUBR,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00120                         break;
00121                 case 0x06:              // FDIV  ST,STi /
00122                         gen_call_function((void*)&FPU_FDIV,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00123                         break;
00124                 case 0x07:              // FDIVR ST,STi /
00125                         gen_call_function((void*)&FPU_FDIVR,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00126                         break;
00127                 default:
00128                         break;
00129                 }
00130         } else { 
00131                 dyn_fill_ea();
00132                 gen_call_function((void*)&FPU_FLD_F32_EA,"%Ddr",DREG(EA)); 
00133                 gen_load_host(&TOP,DREG(TMPB),4);
00134                 dyn_eatree();
00135         }
00136 }
00137 
00138 static void dyn_fpu_esc1(){
00139         dyn_get_modrm();  
00140         if (decode.modrm.val >= 0xc0) { 
00141                 Bitu group=(decode.modrm.val >> 3) & 7;
00142                 Bitu sub=(decode.modrm.val & 7);
00143                 switch (group){
00144                 case 0x00: /* FLD STi */
00145                         gen_protectflags(); 
00146                         gen_load_host(&TOP,DREG(EA),4); 
00147                         gen_dop_word_imm(DOP_ADD,true,DREG(EA),decode.modrm.rm); 
00148                         gen_dop_word_imm(DOP_AND,true,DREG(EA),7); 
00149                         gen_call_function((void*)&FPU_PREP_PUSH,""); 
00150                         gen_load_host(&TOP,DREG(TMPB),4); 
00151                         gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00152                         break;
00153                 case 0x01: /* FXCH STi */
00154                         dyn_fpu_top();
00155                         gen_call_function((void*)&FPU_FXCH,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00156                         break;
00157                 case 0x02: /* FNOP */
00158                         gen_call_function((void*)&FPU_FNOP,"");
00159                         break;
00160                 case 0x03: /* FSTP STi */
00161                         dyn_fpu_top();
00162                         gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00163                         gen_call_function((void*)&FPU_FPOP,"");
00164                         break;   
00165                 case 0x04:
00166                         switch(sub){
00167                         case 0x00:       /* FCHS */
00168                                 gen_call_function((void*)&FPU_FCHS,"");
00169                                 break;
00170                         case 0x01:       /* FABS */
00171                                 gen_call_function((void*)&FPU_FABS,"");
00172                                 break;
00173                         case 0x02:       /* UNKNOWN */
00174                         case 0x03:       /* ILLEGAL */
00175                                 LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub);
00176                                 break;
00177                         case 0x04:       /* FTST */
00178                                 gen_call_function((void*)&FPU_FTST,"");
00179                                 break;
00180                         case 0x05:       /* FXAM */
00181                                 gen_call_function((void*)&FPU_FXAM,"");
00182                                 break;
00183                         case 0x06:       /* FTSTP (cyrix)*/
00184                         case 0x07:       /* UNKNOWN */
00185                                 LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub);
00186                                 break;
00187                         }
00188                         break;
00189                 case 0x05:
00190                         switch(sub){    
00191                         case 0x00:       /* FLD1 */
00192                                 gen_call_function((void*)&FPU_FLD1,"");
00193                                 break;
00194                         case 0x01:       /* FLDL2T */
00195                                 gen_call_function((void*)&FPU_FLDL2T,"");
00196                                 break;
00197                         case 0x02:       /* FLDL2E */
00198                                 gen_call_function((void*)&FPU_FLDL2E,"");
00199                                 break;
00200                         case 0x03:       /* FLDPI */
00201                                 gen_call_function((void*)&FPU_FLDPI,"");
00202                                 break;
00203                         case 0x04:       /* FLDLG2 */
00204                                 gen_call_function((void*)&FPU_FLDLG2,"");
00205                                 break;
00206                         case 0x05:       /* FLDLN2 */
00207                                 gen_call_function((void*)&FPU_FLDLN2,"");
00208                                 break;
00209                         case 0x06:       /* FLDZ*/
00210                                 gen_call_function((void*)&FPU_FLDZ,"");
00211                                 break;
00212                         case 0x07:       /* ILLEGAL */
00213                                 LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub);
00214                                 break;
00215                         }
00216                         break;
00217                 case 0x06:
00218                         switch(sub){
00219                         case 0x00:      /* F2XM1 */
00220                                 gen_call_function((void*)&FPU_F2XM1,"");
00221                                 break;
00222                         case 0x01:      /* FYL2X */
00223                                 gen_call_function((void*)&FPU_FYL2X,"");
00224                                 break;
00225                         case 0x02:      /* FPTAN  */
00226                                 gen_call_function((void*)&FPU_FPTAN,"");
00227                                 break;
00228                         case 0x03:      /* FPATAN */
00229                                 gen_call_function((void*)&FPU_FPATAN,"");
00230                                 break;
00231                         case 0x04:      /* FXTRACT */
00232                                 gen_call_function((void*)&FPU_FXTRACT,"");
00233                                 break;
00234                         case 0x05:      /* FPREM1 */
00235                                 gen_call_function((void*)&FPU_FPREM1,"");
00236                                 break;
00237                         case 0x06:      /* FDECSTP */
00238                                 gen_call_function((void*)&FPU_FDECSTP,"");
00239                                 break;
00240                         case 0x07:      /* FINCSTP */
00241                                 gen_call_function((void*)&FPU_FINCSTP,"");
00242                                 break;
00243                         default:
00244                                 LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub);
00245                                 break;
00246                         }
00247                         break;
00248                 case 0x07:
00249                         switch(sub){
00250                         case 0x00:              /* FPREM */
00251                                 gen_call_function((void*)&FPU_FPREM,"");
00252                                 break;
00253                         case 0x01:              /* FYL2XP1 */
00254                                 gen_call_function((void*)&FPU_FYL2XP1,"");
00255                                 break;
00256                         case 0x02:              /* FSQRT */
00257                                 gen_call_function((void*)&FPU_FSQRT,"");
00258                                 break;
00259                         case 0x03:              /* FSINCOS */
00260                                 gen_call_function((void*)&FPU_FSINCOS,"");
00261                                 break;
00262                         case 0x04:              /* FRNDINT */
00263                                 gen_call_function((void*)&FPU_FRNDINT,"");
00264                                 break;
00265                         case 0x05:              /* FSCALE */
00266                                 gen_call_function((void*)&FPU_FSCALE,"");
00267                                 break;
00268                         case 0x06:              /* FSIN */
00269                                 gen_call_function((void*)&FPU_FSIN,"");
00270                                 break;
00271                         case 0x07:              /* FCOS */
00272                                 gen_call_function((void*)&FPU_FCOS,"");
00273                                 break;
00274                         default:
00275                                 LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub);
00276                                 break;
00277                         }
00278                         break;
00279                 default:
00280                         LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub);
00281                         break;
00282                 }
00283         } else {
00284                 Bitu group=(decode.modrm.val >> 3) & 7;
00285                 Bitu sub=(decode.modrm.val & 7);
00286                 dyn_fill_ea(); 
00287                 switch(group){
00288                 case 0x00: /* FLD float*/
00289                         gen_protectflags(); 
00290                         gen_call_function((void*)&FPU_PREP_PUSH,"");
00291                         gen_load_host(&TOP,DREG(TMPB),4); 
00292                         gen_call_function((void*)&FPU_FLD_F32,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00293                         break;
00294                 case 0x01: /* UNKNOWN */
00295                         LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
00296                         break;
00297                 case 0x02: /* FST float*/
00298                         gen_call_function((void*)&FPU_FST_F32,"%Ddr",DREG(EA));
00299                         break;
00300                 case 0x03: /* FSTP float*/
00301                         gen_call_function((void*)&FPU_FST_F32,"%Ddr",DREG(EA));
00302                         gen_call_function((void*)&FPU_FPOP,"");
00303                         break;
00304                 case 0x04: /* FLDENV */
00305                         gen_call_function((void*)&FPU_FLDENV,"%Ddr",DREG(EA));
00306                         break;
00307                 case 0x05: /* FLDCW */
00308                         gen_call_function((void *)&FPU_FLDCW,"%Ddr",DREG(EA));
00309                         break;
00310                 case 0x06: /* FSTENV */
00311                         gen_call_function((void *)&FPU_FSTENV,"%Ddr",DREG(EA));
00312                         break;
00313                 case 0x07:  /* FNSTCW*/
00314                         gen_call_function((void *)&FPU_FNSTCW,"%Ddr",DREG(EA));
00315                         break;
00316                 default:
00317                         LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
00318                         break;
00319                 }
00320         }
00321 }
00322 
00323 static void dyn_fpu_esc2(){
00324         dyn_get_modrm();  
00325         if (decode.modrm.val >= 0xc0) { 
00326                 Bitu group=(decode.modrm.val >> 3) & 7;
00327                 Bitu sub=(decode.modrm.val & 7);
00328                 switch(group){
00329                 case 0x05:
00330                         switch(sub){
00331                         case 0x01:              /* FUCOMPP */
00332                                 gen_protectflags(); 
00333                                 gen_load_host(&TOP,DREG(EA),4); 
00334                                 gen_dop_word_imm(DOP_ADD,true,DREG(EA),1); 
00335                                 gen_dop_word_imm(DOP_AND,true,DREG(EA),7); 
00336                                 gen_load_host(&TOP,DREG(TMPB),4); 
00337                                 gen_call_function((void *)&FPU_FUCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00338                                 gen_call_function((void *)&FPU_FPOP,"");
00339                                 gen_call_function((void *)&FPU_FPOP,"");
00340                                 break;
00341                         default:
00342                                 LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",group,sub); 
00343                                 break;
00344                         }
00345                         break;
00346                 default:
00347                         LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",group,sub);
00348                         break;
00349                 }
00350         } else {
00351                 dyn_fill_ea(); 
00352                 gen_call_function((void*)&FPU_FLD_I32_EA,"%Ddr",DREG(EA)); 
00353                 gen_load_host(&TOP,DREG(TMPB),4); 
00354                 dyn_eatree();
00355         }
00356 }
00357 
00358 static void dyn_fpu_esc3(){
00359         dyn_get_modrm();  
00360         if (decode.modrm.val >= 0xc0) { 
00361                 Bitu group=(decode.modrm.val >> 3) & 7;
00362                 Bitu sub=(decode.modrm.val & 7);
00363                 switch (group) {
00364                 case 0x04:
00365                         switch (sub) {
00366                         case 0x00:                              //FNENI
00367                         case 0x01:                              //FNDIS
00368                                 LOG(LOG_FPU,LOG_ERROR)("8087 only fpu code used esc 3: group 4: subfuntion :%d",sub);
00369                                 break;
00370                         case 0x02:                              //FNCLEX FCLEX
00371                                 gen_call_function((void*)&FPU_FCLEX,"");
00372                                 break;
00373                         case 0x03:                              //FNINIT FINIT
00374                                 gen_call_function((void*)&FPU_FINIT,"");
00375                                 break;
00376                         case 0x04:                              //FNSETPM
00377                         case 0x05:                              //FRSTPM
00378 //                              LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done");
00379                                 break;
00380                         default:
00381                                 E_Exit("ESC 3:ILLEGAL OPCODE group %d subfunction %d",group,sub);
00382                         }
00383                         break;
00384                 default:
00385                         LOG(LOG_FPU,LOG_WARN)("ESC 3:Unhandled group %d subfunction %d",group,sub);
00386                         break;
00387                 }
00388         } else {
00389                 Bitu group=(decode.modrm.val >> 3) & 7;
00390                 Bitu sub=(decode.modrm.val & 7);
00391                 dyn_fill_ea(); 
00392                 switch(group){
00393                 case 0x00:      /* FILD */
00394                         gen_call_function((void*)&FPU_PREP_PUSH,"");
00395                         gen_protectflags(); 
00396                         gen_load_host(&TOP,DREG(TMPB),4); 
00397                         gen_call_function((void*)&FPU_FLD_I32,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00398                         break;
00399                 case 0x01:      /* FISTTP */
00400                         LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub);
00401                         break;
00402                 case 0x02:      /* FIST */
00403                         gen_call_function((void*)&FPU_FST_I32,"%Ddr",DREG(EA));
00404                         break;
00405                 case 0x03:      /* FISTP */
00406                         gen_call_function((void*)&FPU_FST_I32,"%Ddr",DREG(EA));
00407                         gen_call_function((void*)&FPU_FPOP,"");
00408                         break;
00409                 case 0x05:      /* FLD 80 Bits Real */
00410                         gen_call_function((void*)&FPU_PREP_PUSH,"");
00411                         gen_call_function((void*)&FPU_FLD_F80,"%Ddr",DREG(EA));
00412                         break;
00413                 case 0x07:      /* FSTP 80 Bits Real */
00414                         gen_call_function((void*)&FPU_FST_F80,"%Ddr",DREG(EA));
00415                         gen_call_function((void*)&FPU_FPOP,"");
00416                         break;
00417                 default:
00418                         LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub);
00419                 }
00420         }
00421 }
00422 
00423 static void dyn_fpu_esc4(){
00424         dyn_get_modrm();  
00425         Bitu group=(decode.modrm.val >> 3) & 7;
00426         if (decode.modrm.val >= 0xc0) { 
00427                 dyn_fpu_top();
00428                 switch(group){
00429                 case 0x00:      /* FADD STi,ST*/
00430                         gen_call_function((void*)&FPU_FADD,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00431                         break;
00432                 case 0x01:      /* FMUL STi,ST*/
00433                         gen_call_function((void*)&FPU_FMUL,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00434                         break;
00435                 case 0x02:  /* FCOM*/
00436                         gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00437                         break;
00438                 case 0x03:  /* FCOMP*/
00439                         gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00440                         gen_call_function((void*)&FPU_FPOP,"");
00441                         break;
00442                 case 0x04:  /* FSUBR STi,ST*/
00443                         gen_call_function((void*)&FPU_FSUBR,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00444                         break;
00445                 case 0x05:  /* FSUB  STi,ST*/
00446                         gen_call_function((void*)&FPU_FSUB,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00447                         break;
00448                 case 0x06:  /* FDIVR STi,ST*/
00449                         gen_call_function((void*)&FPU_FDIVR,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00450                         break;
00451                 case 0x07:  /* FDIV STi,ST*/
00452                         gen_call_function((void*)&FPU_FDIV,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00453                         break;
00454                 default:
00455                         break;
00456                 }
00457         } else { 
00458                 dyn_fill_ea(); 
00459                 gen_call_function((void*)&FPU_FLD_F64_EA,"%Ddr",DREG(EA)); 
00460                 gen_load_host(&TOP,DREG(TMPB),4); 
00461                 dyn_eatree();
00462         }
00463 }
00464 
00465 static void dyn_fpu_esc5(){
00466         dyn_get_modrm();  
00467         Bitu group=(decode.modrm.val >> 3) & 7;
00468         Bitu sub=(decode.modrm.val & 7);
00469         if (decode.modrm.val >= 0xc0) { 
00470                 dyn_fpu_top();
00471                 switch(group){
00472                 case 0x00: /* FFREE STi */
00473                         gen_call_function((void*)&FPU_FFREE,"%Ddr",DREG(EA));
00474                         break;
00475                 case 0x01: /* FXCH STi*/
00476                         gen_call_function((void*)&FPU_FXCH,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00477                         break;
00478                 case 0x02: /* FST STi */
00479                         gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00480                         break;
00481                 case 0x03:  /* FSTP STi*/
00482                         gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00483                         gen_call_function((void*)&FPU_FPOP,"");
00484                         break;
00485                 case 0x04:      /* FUCOM STi */
00486                         gen_call_function((void*)&FPU_FUCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00487                         break;
00488                 case 0x05:      /*FUCOMP STi */
00489                         gen_call_function((void*)&FPU_FUCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00490                         gen_call_function((void*)&FPU_FPOP,"");
00491                         break;
00492                 default:
00493                         LOG(LOG_FPU,LOG_WARN)("ESC 5:Unhandled group %d subfunction %d",group,sub);
00494                         break;
00495         }
00496                 gen_releasereg(DREG(EA));
00497                 gen_releasereg(DREG(TMPB));
00498         } else {
00499                 dyn_fill_ea(); 
00500                 switch(group){
00501                 case 0x00:  /* FLD double real*/
00502                         gen_call_function((void*)&FPU_PREP_PUSH,"");
00503                         gen_protectflags(); 
00504                         gen_load_host(&TOP,DREG(TMPB),4); 
00505                         gen_call_function((void*)&FPU_FLD_F64,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00506                         break;
00507                 case 0x01:  /* FISTTP longint*/
00508                         LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub);
00509                         break;
00510                 case 0x02:   /* FST double real*/
00511                         gen_call_function((void*)&FPU_FST_F64,"%Ddr",DREG(EA));
00512                         break;
00513                 case 0x03:      /* FSTP double real*/
00514                         gen_call_function((void*)&FPU_FST_F64,"%Ddr",DREG(EA));
00515                         gen_call_function((void*)&FPU_FPOP,"");
00516                         break;
00517                 case 0x04:      /* FRSTOR */
00518                         gen_call_function((void*)&FPU_FRSTOR,"%Ddr",DREG(EA));
00519                         break;
00520                 case 0x06:      /* FSAVE */
00521                         gen_call_function((void*)&FPU_FSAVE,"%Ddr",DREG(EA));
00522                         break;
00523                 case 0x07:   /*FNSTSW */
00524                         gen_protectflags(); 
00525                         gen_load_host(&TOP,DREG(TMPB),4); 
00526                         gen_call_function((void*)&FPU_SET_TOP,"%Dd",DREG(TMPB));
00527                         gen_load_host(&fpu.sw,DREG(TMPB),4); 
00528                         gen_call_function((void*)&mem_writew,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00529                         break;
00530                 default:
00531                         LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub);
00532                 }
00533         }
00534 }
00535 
00536 static void dyn_fpu_esc6(){
00537         dyn_get_modrm();  
00538         Bitu group=(decode.modrm.val >> 3) & 7;
00539         Bitu sub=(decode.modrm.val & 7);
00540         if (decode.modrm.val >= 0xc0) { 
00541                 dyn_fpu_top();
00542                 switch(group){
00543                 case 0x00:      /*FADDP STi,ST*/
00544                         gen_call_function((void*)&FPU_FADD,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00545                         break;
00546                 case 0x01:      /* FMULP STi,ST*/
00547                         gen_call_function((void*)&FPU_FMUL,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00548                         break;
00549                 case 0x02:  /* FCOMP5*/
00550                         gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00551                         break;  /* TODO IS THIS ALLRIGHT ????????? */
00552                 case 0x03:  /*FCOMPP*/
00553                         if(sub != 1) {
00554                                 LOG(LOG_FPU,LOG_WARN)("ESC 6:Unhandled group %d subfunction %d",group,sub);
00555                                 return;
00556                         }
00557                         gen_load_host(&TOP,DREG(EA),4); 
00558                         gen_dop_word_imm(DOP_ADD,true,DREG(EA),1);
00559                         gen_dop_word_imm(DOP_AND,true,DREG(EA),7);
00560                         gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00561                         gen_call_function((void*)&FPU_FPOP,""); /* extra pop at the bottom*/
00562                         break;
00563                 case 0x04:  /* FSUBRP STi,ST*/
00564                         gen_call_function((void*)&FPU_FSUBR,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00565                         break;
00566                 case 0x05:  /* FSUBP  STi,ST*/
00567                         gen_call_function((void*)&FPU_FSUB,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00568                         break;
00569                 case 0x06:      /* FDIVRP STi,ST*/
00570                         gen_call_function((void*)&FPU_FDIVR,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00571                         break;
00572                 case 0x07:  /* FDIVP STi,ST*/
00573                         gen_call_function((void*)&FPU_FDIV,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00574                         break;
00575                 default:
00576                         break;
00577                 }
00578                 gen_call_function((void*)&FPU_FPOP,"");         
00579         } else {
00580                 dyn_fill_ea(); 
00581                 gen_call_function((void*)&FPU_FLD_I16_EA,"%Ddr",DREG(EA)); 
00582                 gen_load_host(&TOP,DREG(TMPB),4); 
00583                 dyn_eatree();
00584         }
00585 }
00586 
00587 static void dyn_fpu_esc7(){
00588         dyn_get_modrm();  
00589         Bitu group=(decode.modrm.val >> 3) & 7;
00590         Bitu sub=(decode.modrm.val & 7);
00591         if (decode.modrm.val >= 0xc0) { 
00592                 switch (group){
00593                 case 0x00: /* FFREEP STi*/
00594                         dyn_fpu_top();
00595                         gen_call_function((void*)&FPU_FFREE,"%Ddr",DREG(EA));
00596                         gen_call_function((void*)&FPU_FPOP,"");
00597                         break;
00598                 case 0x01: /* FXCH STi*/
00599                         dyn_fpu_top();
00600                         gen_call_function((void*)&FPU_FXCH,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00601                         break;
00602                 case 0x02:  /* FSTP STi*/
00603                 case 0x03:  /* FSTP STi*/
00604                         dyn_fpu_top();
00605                         gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
00606                         gen_call_function((void*)&FPU_FPOP,"");
00607                         break;
00608                 case 0x04:
00609                         switch(sub){
00610                                 case 0x00:     /* FNSTSW AX*/
00611                                         gen_load_host(&TOP,DREG(TMPB),4);
00612                                         gen_call_function((void*)&FPU_SET_TOP,"%Ddr",DREG(TMPB)); 
00613                                         gen_mov_host(&fpu.sw,DREG(EAX),2);
00614                                         break;
00615                                 default:
00616                                         LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub);
00617                                         break;
00618                         }
00619                         break;
00620                 default:
00621                         LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub);
00622                         break;
00623                 }
00624         } else {
00625                 dyn_fill_ea(); 
00626                 switch(group){
00627                 case 0x00:  /* FILD Bit16s */
00628                         gen_call_function((void*)&FPU_PREP_PUSH,"");
00629                         gen_load_host(&TOP,DREG(TMPB),4); 
00630                         gen_call_function((void*)&FPU_FLD_I16,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00631                         break;
00632                 case 0x01:
00633                         LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub);
00634                         break;
00635                 case 0x02:   /* FIST Bit16s */
00636                         gen_call_function((void*)&FPU_FST_I16,"%Ddr",DREG(EA));
00637                         break;
00638                 case 0x03:      /* FISTP Bit16s */
00639                         gen_call_function((void*)&FPU_FST_I16,"%Ddr",DREG(EA));
00640                         gen_call_function((void*)&FPU_FPOP,"");
00641                         break;
00642                 case 0x04:   /* FBLD packed BCD */
00643                         gen_call_function((void*)&FPU_PREP_PUSH,"");
00644                         gen_load_host(&TOP,DREG(TMPB),4);
00645                         gen_call_function((void*)&FPU_FBLD,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00646                         break;
00647                 case 0x05:  /* FILD Bit64s */
00648                         gen_call_function((void*)&FPU_PREP_PUSH,"");
00649                         gen_load_host(&TOP,DREG(TMPB),4);
00650                         gen_call_function((void*)&FPU_FLD_I64,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
00651                         break;
00652                 case 0x06:      /* FBSTP packed BCD */
00653                         gen_call_function((void*)&FPU_FBST,"%Ddr",DREG(EA));
00654                         gen_call_function((void*)&FPU_FPOP,"");
00655                         break;
00656                 case 0x07:  /* FISTP Bit64s */
00657                         gen_call_function((void*)&FPU_FST_I64,"%Ddr",DREG(EA));
00658                         gen_call_function((void*)&FPU_FPOP,"");
00659                         break;
00660                 default:
00661                         LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub);
00662                         break;
00663                 }
00664         }
00665 }
00666 
00667 #endif