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