/* * Copyright (C) 2002-2010 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* $Id: dyn_fpu.h,v 1.8 2009-09-23 20:55:19 c2woody Exp $ */ #include "dosbox.h" #if C_FPU #include #include #include "cross.h" #include "mem.h" #include "fpu.h" #include "cpu.h" static void FPU_FDECSTP(){ TOP = (TOP - 1) & 7; } static void FPU_FINCSTP(){ TOP = (TOP + 1) & 7; } static void FPU_FNSTCW(PhysPt addr){ mem_writew(addr,fpu.cw); } static void FPU_FFREE(Bitu st) { fpu.tags[st]=TAG_Empty; } #if C_FPU_X86 #include "../../fpu/fpu_instructions_x86.h" #else #include "../../fpu/fpu_instructions.h" #endif static INLINE void dyn_fpu_top() { gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); gen_add_imm(FC_OP2,decode.modrm.rm); gen_and_imm(FC_OP2,7); gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); } static INLINE void dyn_fpu_top_swapped() { gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); gen_add_imm(FC_OP1,decode.modrm.rm); gen_and_imm(FC_OP1,7); gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); } static void dyn_eatree() { Bitu group=(decode.modrm.val >> 3) & 7; switch (group){ case 0x00: // FADD ST,STi gen_call_function_R((void*)&FPU_FADD_EA,FC_OP1); break; case 0x01: // FMUL ST,STi gen_call_function_R((void*)&FPU_FMUL_EA,FC_OP1); break; case 0x02: // FCOM STi gen_call_function_R((void*)&FPU_FCOM_EA,FC_OP1); break; case 0x03: // FCOMP STi gen_call_function_R((void*)&FPU_FCOM_EA,FC_OP1); gen_call_function_raw((void*)&FPU_FPOP); break; case 0x04: // FSUB ST,STi gen_call_function_R((void*)&FPU_FSUB_EA,FC_OP1); break; case 0x05: // FSUBR ST,STi gen_call_function_R((void*)&FPU_FSUBR_EA,FC_OP1); break; case 0x06: // FDIV ST,STi gen_call_function_R((void*)&FPU_FDIV_EA,FC_OP1); break; case 0x07: // FDIVR ST,STi gen_call_function_R((void*)&FPU_FDIVR_EA,FC_OP1); break; default: break; } } static void dyn_fpu_esc0(){ dyn_get_modrm(); if (decode.modrm.val >= 0xc0) { dyn_fpu_top(); switch (decode.modrm.reg){ case 0x00: //FADD ST,STi gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2); break; case 0x01: // FMUL ST,STi gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2); break; case 0x02: // FCOM STi gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); break; case 0x03: // FCOMP STi gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); gen_call_function_raw((void*)&FPU_FPOP); break; case 0x04: // FSUB ST,STi gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2); break; case 0x05: // FSUBR ST,STi gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2); break; case 0x06: // FDIV ST,STi gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2); break; case 0x07: // FDIVR ST,STi gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2); break; default: break; } } else { dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FLD_F32_EA,FC_ADDR); gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); dyn_eatree(); } } static void dyn_fpu_esc1(){ dyn_get_modrm(); if (decode.modrm.val >= 0xc0) { switch (decode.modrm.reg){ case 0x00: /* FLD STi */ gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); gen_add_imm(FC_OP1,decode.modrm.rm); gen_and_imm(FC_OP1,7); gen_protect_reg(FC_OP1); gen_call_function_raw((void*)&FPU_PREP_PUSH); gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); gen_restore_reg(FC_OP1); gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); break; case 0x01: /* FXCH STi */ dyn_fpu_top(); gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2); break; case 0x02: /* FNOP */ gen_call_function_raw((void*)&FPU_FNOP); break; case 0x03: /* FSTP STi */ dyn_fpu_top(); gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); gen_call_function_raw((void*)&FPU_FPOP); break; case 0x04: switch(decode.modrm.rm){ case 0x00: /* FCHS */ gen_call_function_raw((void*)&FPU_FCHS); break; case 0x01: /* FABS */ gen_call_function_raw((void*)&FPU_FABS); break; case 0x02: /* UNKNOWN */ case 0x03: /* ILLEGAL */ LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); break; case 0x04: /* FTST */ gen_call_function_raw((void*)&FPU_FTST); break; case 0x05: /* FXAM */ gen_call_function_raw((void*)&FPU_FXAM); break; case 0x06: /* FTSTP (cyrix)*/ case 0x07: /* UNKNOWN */ LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); break; } break; case 0x05: switch(decode.modrm.rm){ case 0x00: /* FLD1 */ gen_call_function_raw((void*)&FPU_FLD1); break; case 0x01: /* FLDL2T */ gen_call_function_raw((void*)&FPU_FLDL2T); break; case 0x02: /* FLDL2E */ gen_call_function_raw((void*)&FPU_FLDL2E); break; case 0x03: /* FLDPI */ gen_call_function_raw((void*)&FPU_FLDPI); break; case 0x04: /* FLDLG2 */ gen_call_function_raw((void*)&FPU_FLDLG2); break; case 0x05: /* FLDLN2 */ gen_call_function_raw((void*)&FPU_FLDLN2); break; case 0x06: /* FLDZ*/ gen_call_function_raw((void*)&FPU_FLDZ); break; case 0x07: /* ILLEGAL */ LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); break; } break; case 0x06: switch(decode.modrm.rm){ case 0x00: /* F2XM1 */ gen_call_function_raw((void*)&FPU_F2XM1); break; case 0x01: /* FYL2X */ gen_call_function_raw((void*)&FPU_FYL2X); break; case 0x02: /* FPTAN */ gen_call_function_raw((void*)&FPU_FPTAN); break; case 0x03: /* FPATAN */ gen_call_function_raw((void*)&FPU_FPATAN); break; case 0x04: /* FXTRACT */ gen_call_function_raw((void*)&FPU_FXTRACT); break; case 0x05: /* FPREM1 */ gen_call_function_raw((void*)&FPU_FPREM1); break; case 0x06: /* FDECSTP */ gen_call_function_raw((void*)&FPU_FDECSTP); break; case 0x07: /* FINCSTP */ gen_call_function_raw((void*)&FPU_FINCSTP); break; default: LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); break; } break; case 0x07: switch(decode.modrm.rm){ case 0x00: /* FPREM */ gen_call_function_raw((void*)&FPU_FPREM); break; case 0x01: /* FYL2XP1 */ gen_call_function_raw((void*)&FPU_FYL2XP1); break; case 0x02: /* FSQRT */ gen_call_function_raw((void*)&FPU_FSQRT); break; case 0x03: /* FSINCOS */ gen_call_function_raw((void*)&FPU_FSINCOS); break; case 0x04: /* FRNDINT */ gen_call_function_raw((void*)&FPU_FRNDINT); break; case 0x05: /* FSCALE */ gen_call_function_raw((void*)&FPU_FSCALE); break; case 0x06: /* FSIN */ gen_call_function_raw((void*)&FPU_FSIN); break; case 0x07: /* FCOS */ gen_call_function_raw((void*)&FPU_FCOS); break; default: LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); break; } break; default: LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); break; } } else { switch(decode.modrm.reg){ case 0x00: /* FLD float*/ gen_call_function_raw((void*)&FPU_PREP_PUSH); dyn_fill_ea(FC_OP1); gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); gen_call_function_RR((void*)&FPU_FLD_F32,FC_OP1,FC_OP2); break; case 0x01: /* UNKNOWN */ LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); break; case 0x02: /* FST float*/ dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FST_F32,FC_ADDR); break; case 0x03: /* FSTP float*/ dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FST_F32,FC_ADDR); gen_call_function_raw((void*)&FPU_FPOP); break; case 0x04: /* FLDENV */ dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FLDENV,FC_ADDR); break; case 0x05: /* FLDCW */ dyn_fill_ea(FC_ADDR); gen_call_function_R((void *)&FPU_FLDCW,FC_ADDR); break; case 0x06: /* FSTENV */ dyn_fill_ea(FC_ADDR); gen_call_function_R((void *)&FPU_FSTENV,FC_ADDR); break; case 0x07: /* FNSTCW*/ dyn_fill_ea(FC_ADDR); gen_call_function_R((void *)&FPU_FNSTCW,FC_ADDR); break; default: LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); break; } } } static void dyn_fpu_esc2(){ dyn_get_modrm(); if (decode.modrm.val >= 0xc0) { switch(decode.modrm.reg){ case 0x05: switch(decode.modrm.rm){ case 0x01: /* FUCOMPP */ gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); gen_add_imm(FC_OP2,1); gen_and_imm(FC_OP2,7); gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); gen_call_function_RR((void *)&FPU_FUCOM,FC_OP1,FC_OP2); gen_call_function_raw((void *)&FPU_FPOP); gen_call_function_raw((void *)&FPU_FPOP); break; default: LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); break; } break; default: LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); break; } } else { dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FLD_I32_EA,FC_ADDR); gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); dyn_eatree(); } } static void dyn_fpu_esc3(){ dyn_get_modrm(); if (decode.modrm.val >= 0xc0) { switch (decode.modrm.reg) { case 0x04: switch (decode.modrm.rm) { case 0x00: //FNENI case 0x01: //FNDIS LOG(LOG_FPU,LOG_ERROR)("8087 only fpu code used esc 3: group 4: subfuntion: %d",decode.modrm.rm); break; case 0x02: //FNCLEX FCLEX gen_call_function_raw((void*)&FPU_FCLEX); break; case 0x03: //FNINIT FINIT gen_call_function_raw((void*)&FPU_FINIT); break; case 0x04: //FNSETPM case 0x05: //FRSTPM // LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done"); break; default: E_Exit("ESC 3:ILLEGAL OPCODE group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); } break; default: LOG(LOG_FPU,LOG_WARN)("ESC 3:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); break; } } else { switch(decode.modrm.reg){ case 0x00: /* FILD */ gen_call_function_raw((void*)&FPU_PREP_PUSH); dyn_fill_ea(FC_OP1); gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); gen_call_function_RR((void*)&FPU_FLD_I32,FC_OP1,FC_OP2); break; case 0x01: /* FISTTP */ LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); break; case 0x02: /* FIST */ dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FST_I32,FC_ADDR); break; case 0x03: /* FISTP */ dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FST_I32,FC_ADDR); gen_call_function_raw((void*)&FPU_FPOP); break; case 0x05: /* FLD 80 Bits Real */ gen_call_function_raw((void*)&FPU_PREP_PUSH); dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FLD_F80,FC_ADDR); break; case 0x07: /* FSTP 80 Bits Real */ dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FST_F80,FC_ADDR); gen_call_function_raw((void*)&FPU_FPOP); break; default: LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); } } } static void dyn_fpu_esc4(){ dyn_get_modrm(); if (decode.modrm.val >= 0xc0) { switch(decode.modrm.reg){ case 0x00: /* FADD STi,ST*/ dyn_fpu_top_swapped(); gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2); break; case 0x01: /* FMUL STi,ST*/ dyn_fpu_top_swapped(); gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2); break; case 0x02: /* FCOM*/ dyn_fpu_top(); gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); break; case 0x03: /* FCOMP*/ dyn_fpu_top(); gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); gen_call_function_raw((void*)&FPU_FPOP); break; case 0x04: /* FSUBR STi,ST*/ dyn_fpu_top_swapped(); gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2); break; case 0x05: /* FSUB STi,ST*/ dyn_fpu_top_swapped(); gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2); break; case 0x06: /* FDIVR STi,ST*/ dyn_fpu_top_swapped(); gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2); break; case 0x07: /* FDIV STi,ST*/ dyn_fpu_top_swapped(); gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2); break; default: break; } } else { dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FLD_F64_EA,FC_ADDR); gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); dyn_eatree(); } } static void dyn_fpu_esc5(){ dyn_get_modrm(); if (decode.modrm.val >= 0xc0) { dyn_fpu_top(); switch(decode.modrm.reg){ case 0x00: /* FFREE STi */ gen_call_function_R((void*)&FPU_FFREE,FC_OP2); break; case 0x01: /* FXCH STi*/ gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2); break; case 0x02: /* FST STi */ gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); break; case 0x03: /* FSTP STi*/ gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); gen_call_function_raw((void*)&FPU_FPOP); break; case 0x04: /* FUCOM STi */ gen_call_function_RR((void*)&FPU_FUCOM,FC_OP1,FC_OP2); break; case 0x05: /*FUCOMP STi */ gen_call_function_RR((void*)&FPU_FUCOM,FC_OP1,FC_OP2); gen_call_function_raw((void*)&FPU_FPOP); break; default: LOG(LOG_FPU,LOG_WARN)("ESC 5:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); break; } } else { switch(decode.modrm.reg){ case 0x00: /* FLD double real*/ gen_call_function_raw((void*)&FPU_PREP_PUSH); dyn_fill_ea(FC_OP1); gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); gen_call_function_RR((void*)&FPU_FLD_F64,FC_OP1,FC_OP2); break; case 0x01: /* FISTTP longint*/ LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); break; case 0x02: /* FST double real*/ dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FST_F64,FC_ADDR); break; case 0x03: /* FSTP double real*/ dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FST_F64,FC_ADDR); gen_call_function_raw((void*)&FPU_FPOP); break; case 0x04: /* FRSTOR */ dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FRSTOR,FC_ADDR); break; case 0x06: /* FSAVE */ dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FSAVE,FC_ADDR); break; case 0x07: /*FNSTSW */ gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); gen_call_function_R((void*)&FPU_SET_TOP,FC_OP1); dyn_fill_ea(FC_OP1); gen_mov_word_to_reg(FC_OP2,(void*)(&fpu.sw),true); gen_call_function_RR((void*)&mem_writew,FC_OP1,FC_OP2); break; default: LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); } } } static void dyn_fpu_esc6(){ dyn_get_modrm(); if (decode.modrm.val >= 0xc0) { switch(decode.modrm.reg){ case 0x00: /*FADDP STi,ST*/ dyn_fpu_top_swapped(); gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2); break; case 0x01: /* FMULP STi,ST*/ dyn_fpu_top_swapped(); gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2); break; case 0x02: /* FCOMP5*/ dyn_fpu_top(); gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); break; /* TODO IS THIS ALLRIGHT ????????? */ case 0x03: /*FCOMPP*/ if(decode.modrm.rm != 1) { LOG(LOG_FPU,LOG_WARN)("ESC 6:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); return; } gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); gen_add_imm(FC_OP2,1); gen_and_imm(FC_OP2,7); gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); gen_call_function_raw((void*)&FPU_FPOP); /* extra pop at the bottom*/ break; case 0x04: /* FSUBRP STi,ST*/ dyn_fpu_top_swapped(); gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2); break; case 0x05: /* FSUBP STi,ST*/ dyn_fpu_top_swapped(); gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2); break; case 0x06: /* FDIVRP STi,ST*/ dyn_fpu_top_swapped(); gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2); break; case 0x07: /* FDIVP STi,ST*/ dyn_fpu_top_swapped(); gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2); break; default: break; } gen_call_function_raw((void*)&FPU_FPOP); } else { dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FLD_I16_EA,FC_ADDR); gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); dyn_eatree(); } } static void dyn_fpu_esc7(){ dyn_get_modrm(); if (decode.modrm.val >= 0xc0) { switch (decode.modrm.reg){ case 0x00: /* FFREEP STi */ dyn_fpu_top(); gen_call_function_R((void*)&FPU_FFREE,FC_OP2); gen_call_function_raw((void*)&FPU_FPOP); break; case 0x01: /* FXCH STi*/ dyn_fpu_top(); gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2); break; case 0x02: /* FSTP STi*/ case 0x03: /* FSTP STi*/ dyn_fpu_top(); gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); gen_call_function_raw((void*)&FPU_FPOP); break; case 0x04: switch(decode.modrm.rm){ case 0x00: /* FNSTSW AX*/ gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); gen_call_function_R((void*)&FPU_SET_TOP,FC_OP1); gen_mov_word_to_reg(FC_OP1,(void*)(&fpu.sw),false); MOV_REG_WORD16_FROM_HOST_REG(FC_OP1,DRC_REG_EAX); break; default: LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); break; } break; default: LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); break; } } else { switch(decode.modrm.reg){ case 0x00: /* FILD Bit16s */ gen_call_function_raw((void*)&FPU_PREP_PUSH); dyn_fill_ea(FC_OP1); gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); gen_call_function_RR((void*)&FPU_FLD_I16,FC_OP1,FC_OP2); break; case 0x01: LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); break; case 0x02: /* FIST Bit16s */ dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FST_I16,FC_ADDR); break; case 0x03: /* FISTP Bit16s */ dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FST_I16,FC_ADDR); gen_call_function_raw((void*)&FPU_FPOP); break; case 0x04: /* FBLD packed BCD */ gen_call_function_raw((void*)&FPU_PREP_PUSH); dyn_fill_ea(FC_OP1); gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); gen_call_function_RR((void*)&FPU_FBLD,FC_OP1,FC_OP2); break; case 0x05: /* FILD Bit64s */ gen_call_function_raw((void*)&FPU_PREP_PUSH); dyn_fill_ea(FC_OP1); gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); gen_call_function_RR((void*)&FPU_FLD_I64,FC_OP1,FC_OP2); break; case 0x06: /* FBSTP packed BCD */ dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FBST,FC_ADDR); gen_call_function_raw((void*)&FPU_FPOP); break; case 0x07: /* FISTP Bit64s */ dyn_fill_ea(FC_ADDR); gen_call_function_R((void*)&FPU_FST_I64,FC_ADDR); gen_call_function_raw((void*)&FPU_FPOP); break; default: LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); break; } } } #endif