DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/cpu/core_dyn_x86/decoder.h
00001 /*
00002  *  Copyright (C) 2002-2015  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 #define X86_DYNFPU_DH_ENABLED
00021 #define X86_INLINED_MEMACCESS
00022 
00023 #define X86_DYNREC_MMX_ENABLED
00024 
00025 #ifdef X86_DYNREC_MMX_ENABLED
00026 void dyn_mmx_restore();
00027 #endif
00028 
00029 enum REP_Type {
00030         REP_NONE=0,REP_NZ,REP_Z
00031 };
00032 
00033 static struct DynDecode {
00034         PhysPt code;
00035         PhysPt code_start;
00036         PhysPt op_start;
00037         bool big_op;
00038         bool big_addr;
00039         REP_Type rep;
00040         Bitu cycles;
00041         CacheBlock * block;
00042         CacheBlock * active_block;
00043         struct {
00044                 CodePageHandler * code; 
00045                 Bitu index;
00046                 Bit8u * wmap;
00047                 Bit8u * invmap;
00048                 Bitu first;
00049         } page;
00050         struct {
00051                 Bitu val;
00052                 Bitu mod;
00053                 Bitu rm;
00054                 Bitu reg;
00055         } modrm;
00056         DynReg * segprefix;
00057 } decode;
00058 
00059 static bool MakeCodePage(Bitu lin_addr,CodePageHandler * &cph) {
00060         Bit8u rdval;
00061         //Ensure page contains memory:
00062         if (GCC_UNLIKELY(mem_readb_checked(lin_addr,&rdval))) return true;
00063         PageHandler * handler=get_tlb_readhandler(lin_addr);
00064         if (handler->getFlags() & PFLAG_HASCODE) {
00065                 cph=( CodePageHandler *)handler;
00066                 return false;
00067         }
00068         if (handler->getFlags() & PFLAG_NOCODE) {
00069                         LOG_MSG("DYNX86:Can't run code in this page!");
00070                         cph=0;          return false;
00071                 }
00072         Bitu lin_page=lin_addr >> 12;
00073         Bitu phys_page=lin_page;
00074         if (!PAGING_MakePhysPage(phys_page)) {
00075                 LOG_MSG("DYNX86:Can't find physpage for lin addr %x", lin_addr);
00076                 cph=0;          return false;
00077         }
00078         /* Find a free CodePage */
00079         if (!cache.free_pages) {
00080                 if (cache.used_pages!=decode.page.code) cache.used_pages->ClearRelease();
00081                 else {
00082                         if ((cache.used_pages->next) && (cache.used_pages->next!=decode.page.code))
00083                                 cache.used_pages->next->ClearRelease();
00084                         else {
00085                                 LOG_MSG("DYNX86:Invalid cache links");
00086                                 cache.used_pages->ClearRelease();
00087                         }
00088                 }
00089         }
00090         CodePageHandler * cpagehandler=cache.free_pages;
00091         cache.free_pages=cache.free_pages->next;
00092         cpagehandler->prev=cache.last_page;
00093         cpagehandler->next=0;
00094         if (cache.last_page) cache.last_page->next=cpagehandler;
00095         cache.last_page=cpagehandler;
00096         if (!cache.used_pages) cache.used_pages=cpagehandler;
00097         cpagehandler->SetupAt(phys_page,handler);
00098         MEM_SetPageHandler(phys_page,1,cpagehandler);
00099         PAGING_UnlinkPages(lin_page,1);
00100         cph=cpagehandler;
00101         return false;
00102 }
00103 
00104 static Bit8u decode_fetchb(void) {
00105         if (GCC_UNLIKELY(decode.page.index>=4096)) {
00106         /* Advance to the next page */
00107                 decode.active_block->page.end=4095;
00108                 /* trigger possible page fault here */
00109                 decode.page.first++;
00110                 Bitu fetchaddr=decode.page.first << 12;
00111                 mem_readb(fetchaddr);
00112                 MakeCodePage(fetchaddr,decode.page.code);
00113                 CacheBlock * newblock=cache_getblock();
00114                 decode.active_block->crossblock=newblock;
00115                 newblock->crossblock=decode.active_block;
00116                 decode.active_block=newblock;
00117                 decode.active_block->page.start=0;
00118                 decode.page.code->AddCrossBlock(decode.active_block);
00119                 decode.page.wmap=decode.page.code->write_map;
00120                 decode.page.invmap=decode.page.code->invalidation_map;
00121                 decode.page.index=0;
00122         }
00123         decode.page.wmap[decode.page.index]+=0x01;
00124         decode.page.index++;
00125         decode.code+=1;
00126         return mem_readb(decode.code-1);
00127 }
00128 static Bit16u decode_fetchw(void) {
00129         if (GCC_UNLIKELY(decode.page.index>=4095)) {
00130                 Bit16u val=decode_fetchb();
00131                 val|=decode_fetchb() << 8;
00132                 return val;
00133         }
00134         *(Bit16u *)&decode.page.wmap[decode.page.index]+=0x0101;
00135         decode.code+=2;decode.page.index+=2;
00136         return mem_readw(decode.code-2);
00137 }
00138 static Bit32u decode_fetchd(void) {
00139         if (GCC_UNLIKELY(decode.page.index>=4093)) {
00140                 Bit32u val=decode_fetchb();
00141                 val|=decode_fetchb() << 8;
00142                 val|=decode_fetchb() << 16;
00143                 val|=decode_fetchb() << 24;
00144                 return val;
00145         /* Advance to the next page */
00146         }
00147         *(Bit32u *)&decode.page.wmap[decode.page.index]+=0x01010101;
00148         decode.code+=4;decode.page.index+=4;
00149         return mem_readd(decode.code-4);
00150 }
00151 
00152 #define START_WMMEM 64
00153 
00154 static INLINE void decode_increase_wmapmask(Bitu size) {
00155         Bitu mapidx;
00156         CacheBlock* activecb=decode.active_block; 
00157         if (GCC_UNLIKELY(!activecb->cache.wmapmask)) {
00158                 activecb->cache.wmapmask=(Bit8u*)malloc(START_WMMEM);
00159                 memset(activecb->cache.wmapmask,0,START_WMMEM);
00160                 activecb->cache.maskstart=decode.page.index;
00161                 activecb->cache.masklen=START_WMMEM;
00162                 mapidx=0;
00163         } else {
00164                 mapidx=decode.page.index-activecb->cache.maskstart;
00165                 if (GCC_UNLIKELY(mapidx+size>=activecb->cache.masklen)) {
00166                         Bitu newmasklen=activecb->cache.masklen*4;
00167                         if (newmasklen<mapidx+size) newmasklen=((mapidx+size)&~3)*2;
00168                         Bit8u* tempmem=(Bit8u*)malloc(newmasklen);
00169                         memset(tempmem,0,newmasklen);
00170                         memcpy(tempmem,activecb->cache.wmapmask,activecb->cache.masklen);
00171                         free(activecb->cache.wmapmask);
00172                         activecb->cache.wmapmask=tempmem;
00173                         activecb->cache.masklen=newmasklen;
00174                 }
00175         }
00176         switch (size) {
00177                 case 1 : activecb->cache.wmapmask[mapidx]+=0x01; break;
00178                 case 2 : (*(Bit16u*)&activecb->cache.wmapmask[mapidx])+=0x0101; break;
00179                 case 4 : (*(Bit32u*)&activecb->cache.wmapmask[mapidx])+=0x01010101; break;
00180         }
00181 }
00182 
00183 static bool decode_fetchb_imm(Bitu & val) {
00184         if (decode.page.index<4096) {
00185                 if (decode.page.invmap != NULL) {
00186                         if (decode.page.invmap[decode.page.index] == 0) {
00187                                 val=(Bit32u)decode_fetchb();
00188                                 return false;
00189                         }
00190                         HostPt tlb_addr=get_tlb_read(decode.code);
00191                         if (tlb_addr) {
00192                                 val=(Bitu)(tlb_addr+decode.code);
00193                                 decode_increase_wmapmask(1);
00194                                 decode.code++;
00195                                 decode.page.index++;
00196                                 return true;
00197                         }
00198                 }
00199         }
00200         val=(Bit32u)decode_fetchb();
00201         return false;
00202 }
00203 static bool decode_fetchw_imm(Bitu & val) {
00204         if (decode.page.index<4095) {
00205         if (decode.page.invmap != NULL) {
00206             if ((decode.page.invmap[decode.page.index] == 0) &&
00207                 (decode.page.invmap[decode.page.index + 1] == 0)
00208             ) {
00209                                 val=decode_fetchw();
00210                                 return false;
00211                         }
00212                         HostPt tlb_addr=get_tlb_read(decode.code);
00213                         if (tlb_addr) {
00214                                 val=(Bitu)(tlb_addr+decode.code);
00215                                 decode_increase_wmapmask(2);
00216                                 decode.code+=2;
00217                                 decode.page.index+=2;
00218                                 return true;
00219                         }
00220                 }
00221         }
00222         val=decode_fetchw();
00223         return false;
00224 }
00225 static bool decode_fetchd_imm(Bitu & val) {
00226         if (decode.page.index<4093) {
00227         if (decode.page.invmap != NULL) {
00228             if ((decode.page.invmap[decode.page.index] == 0) &&
00229                 (decode.page.invmap[decode.page.index + 1] == 0) &&
00230                 (decode.page.invmap[decode.page.index + 2] == 0) &&
00231                 (decode.page.invmap[decode.page.index + 3] == 0)
00232             ) {
00233                                 val=decode_fetchd();
00234                                 return false;
00235                         }
00236                         HostPt tlb_addr=get_tlb_read(decode.code);
00237                         if (tlb_addr) {
00238                                 val=(Bitu)(tlb_addr+decode.code);
00239                                 decode_increase_wmapmask(4);
00240                                 decode.code+=4;
00241                                 decode.page.index+=4;
00242                                 return true;
00243                         }
00244                 }
00245         }
00246         val=decode_fetchd();
00247         return false;
00248 }
00249 
00250 
00251 static void dyn_reduce_cycles(void) {
00252         gen_protectflags();
00253         if (!decode.cycles) decode.cycles++;
00254         gen_dop_word_imm(DOP_SUB,true,DREG(CYCLES),decode.cycles);
00255 }
00256 
00257 static void dyn_save_noncritical_regs(void) {
00258         gen_releasereg(DREG(EAX));
00259         gen_releasereg(DREG(ECX));
00260         gen_releasereg(DREG(EDX));
00261         gen_releasereg(DREG(EBX));
00262         gen_releasereg(DREG(ESP));
00263         gen_releasereg(DREG(EBP));
00264         gen_releasereg(DREG(ESI));
00265         gen_releasereg(DREG(EDI));
00266 }
00267 
00268 static void dyn_save_critical_regs(void) {
00269         dyn_save_noncritical_regs();
00270         gen_releasereg(DREG(FLAGS));
00271         gen_releasereg(DREG(EIP));
00272         gen_releasereg(DREG(CYCLES));
00273 }
00274 
00275 static void dyn_set_eip_last_end(DynReg * endreg) {
00276         gen_protectflags();
00277         gen_lea(endreg,DREG(EIP),0,0,decode.code-decode.code_start);
00278         gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),decode.op_start-decode.code_start);
00279 }
00280 
00281 static INLINE void dyn_set_eip_end(void) {
00282         gen_protectflags();
00283         gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(EIP),decode.code-decode.code_start);
00284 }
00285 
00286 static INLINE void dyn_set_eip_end(DynReg * /*endreg*/) {
00287         gen_protectflags();
00288         if (cpu.code.big) gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(EIP));
00289         else gen_extend_word(false,DREG(TMPW),DREG(EIP));
00290         gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(TMPW),decode.code-decode.code_start);
00291 }
00292 
00293 static INLINE void dyn_set_eip_last(void) {
00294         gen_protectflags();
00295         gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(EIP),decode.op_start-decode.code_start);
00296 }
00297 
00298 
00299 enum save_info_type {db_exception, cycle_check, normal, fpu_restore};
00300 
00301 
00302 static struct {
00303         save_info_type type;
00304         DynState state;
00305         Bit8u * branch_pos;
00306         Bit32u eip_change;
00307         Bitu cycles;
00308         Bit8u * return_pos;
00309 } save_info[512];
00310 
00311 Bitu used_save_info=0;
00312 
00313 
00314 static BlockReturn DynRunException(Bit32u eip_add,Bit32u cycle_sub,Bit32u dflags) {
00315         reg_flags=(dflags&FMASK_TEST) | (reg_flags&(~FMASK_TEST));
00316         reg_eip+=eip_add;
00317         CPU_Cycles-=cycle_sub;
00318         if (cpu.exception.which==SMC_CURRENT_BLOCK) return BR_SMCBlock;
00319         CPU_Exception(cpu.exception.which,cpu.exception.error);
00320         return BR_Normal;
00321 }
00322 
00323 static void dyn_check_bool_exception(DynReg * check) {
00324         gen_dop_byte(DOP_OR,check,0,check,0);
00325         save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ);
00326         dyn_savestate(&save_info[used_save_info].state);
00327         if (!decode.cycles) decode.cycles++;
00328         save_info[used_save_info].cycles=decode.cycles;
00329         save_info[used_save_info].eip_change=decode.op_start-decode.code_start;
00330         if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff;
00331         save_info[used_save_info].type=db_exception;
00332         used_save_info++;
00333 }
00334 
00335 static void dyn_check_bool_exception_al(void) {
00336         cache_addw(0xc00a);             // or al, al
00337         save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ);
00338         dyn_savestate(&save_info[used_save_info].state);
00339         if (!decode.cycles) decode.cycles++;
00340         save_info[used_save_info].cycles=decode.cycles;
00341         save_info[used_save_info].eip_change=decode.op_start-decode.code_start;
00342         if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff;
00343         save_info[used_save_info].type=db_exception;
00344         used_save_info++;
00345 }
00346 
00347 #include "pic.h"
00348 
00349 static void dyn_check_irqrequest(void) {
00350         gen_load_host(&PIC_IRQCheck,DREG(TMPB),4);
00351         gen_dop_word(DOP_OR,true,DREG(TMPB),DREG(TMPB));
00352         save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ);
00353         gen_releasereg(DREG(TMPB));
00354         dyn_savestate(&save_info[used_save_info].state);
00355         if (!decode.cycles) decode.cycles++;
00356         save_info[used_save_info].cycles=decode.cycles;
00357         save_info[used_save_info].eip_change=decode.code-decode.code_start;
00358         if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff;
00359         save_info[used_save_info].type=normal;
00360         used_save_info++;
00361 }
00362 
00363 static void dyn_check_bool_exception_ne(void) {
00364         save_info[used_save_info].branch_pos=gen_create_branch_long(BR_Z);
00365         dyn_savestate(&save_info[used_save_info].state);
00366         if (!decode.cycles) decode.cycles++;
00367         save_info[used_save_info].cycles=decode.cycles;
00368         save_info[used_save_info].eip_change=decode.op_start-decode.code_start;
00369         if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff;
00370         save_info[used_save_info].type=db_exception;
00371         used_save_info++;
00372 }
00373 
00374 static void dyn_fill_blocks(void) {
00375         GenReg *gr;
00376         for (Bitu sct=0; sct<used_save_info; sct++) {
00377                 gen_fill_branch_long(save_info[sct].branch_pos);
00378                 switch (save_info[sct].type) {
00379                         case db_exception:
00380                                 dyn_loadstate(&save_info[sct].state);
00381                                 decode.cycles=save_info[sct].cycles;
00382                                 dyn_save_critical_regs();
00383                                 if (cpu.code.big) gen_call_function((void *)&DynRunException,"%Id%Id%F",save_info[sct].eip_change,save_info[sct].cycles);
00384                                 else gen_call_function((void *)&DynRunException,"%Iw%Id%F",save_info[sct].eip_change,save_info[sct].cycles);
00385                                 gen_return_fast(BR_Normal,true);
00386                                 break;
00387                         case cycle_check:
00388                                 gen_return(BR_Cycles);
00389                                 break;
00390                         case normal:
00391                                 dyn_loadstate(&save_info[sct].state);
00392                                 gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),save_info[sct].eip_change);
00393                                 dyn_save_critical_regs();
00394                                 gen_return(BR_Cycles);
00395                                 break;
00396                         case fpu_restore:
00397                                 dyn_loadstate(&save_info[sct].state);
00398                                 gen_load_host(&dyn_dh_fpu.state_used,DREG(TMPB),4);
00399                                 gen_sop_word(SOP_INC,true,DREG(TMPB));
00400                                 gr=FindDynReg(DREG(TMPB));
00401                                 cache_addb(0xdd);       // FRSTOR fpu.state (fpu_restore)
00402                                 cache_addb(0x25);
00403                                 cache_addd((uintptr_t)(&(dyn_dh_fpu.state[0])));
00404                                 cache_addb(0x89);       // mov fpu.state_used,1
00405                                 cache_addb(0x05|(gr->index<<3));
00406                                 cache_addd((uintptr_t)(&(dyn_dh_fpu.state_used)));
00407                                 gen_releasereg(DREG(TMPB));
00408                                 dyn_synchstate(&save_info[sct].state);
00409                                 gen_create_jump(save_info[sct].return_pos);
00410                                 break;
00411                 }
00412         }
00413         used_save_info=0;
00414 }
00415 
00416 
00417 #if !defined(X86_INLINED_MEMACCESS)
00418 static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) {
00419         gen_protectflags();
00420         gen_call_function((void *)&mem_readb_checked,"%Dd%Id",addr,&core_dyn.readdata);
00421         dyn_check_bool_exception_al();
00422         gen_mov_host(&core_dyn.readdata,dst,1,high);
00423 }
00424 static void dyn_write_byte(DynReg * addr,DynReg * val,Bitu high) {
00425         gen_protectflags();
00426         if (high) gen_call_function((void *)&mem_writeb_checked,"%Dd%Dh",addr,val);
00427         else gen_call_function((void *)&mem_writeb_checked,"%Dd%Dd",addr,val);
00428         dyn_check_bool_exception_al();
00429 }
00430 static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) {
00431         gen_protectflags();
00432         if (dword) gen_call_function((void *)&mem_readd_checked,"%Dd%Id",addr,&core_dyn.readdata);
00433         else gen_call_function((void *)&mem_readw_checked,"%Dd%Id",addr,&core_dyn.readdata);
00434         dyn_check_bool_exception_al();
00435         gen_mov_host(&core_dyn.readdata,dst,dword?4:2);
00436 }
00437 static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) {
00438         gen_protectflags();
00439         if (dword) gen_call_function((void *)&mem_writed_checked,"%Dd%Dd",addr,val);
00440         else gen_call_function((void *)&mem_writew_checked,"%Dd%Dd",addr,val);
00441         dyn_check_bool_exception_al();
00442 }
00443 static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) {
00444         gen_protectflags();
00445         gen_call_function((void *)&mem_readb_checked,"%Ddr%Id",addr,&core_dyn.readdata);
00446         dyn_check_bool_exception_al();
00447         gen_mov_host(&core_dyn.readdata,dst,1,high);
00448 }
00449 static void dyn_write_byte_release(DynReg * addr,DynReg * val,Bitu high) {
00450         gen_protectflags();
00451         if (high) gen_call_function((void *)&mem_writeb_checked,"%Ddr%Dh",addr,val);
00452         else gen_call_function((void *)&mem_writeb_checked,"%Ddr%Dd",addr,val);
00453         dyn_check_bool_exception_al();
00454 }
00455 static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) {
00456         gen_protectflags();
00457         if (dword) gen_call_function((void *)&mem_readd_checked,"%Ddr%Id",addr,&core_dyn.readdata);
00458         else gen_call_function((void *)&mem_readw_checked,"%Ddr%Id",addr,&core_dyn.readdata);
00459         dyn_check_bool_exception_al();
00460         gen_mov_host(&core_dyn.readdata,dst,dword?4:2);
00461 }
00462 static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) {
00463         gen_protectflags();
00464         if (dword) gen_call_function((void *)&mem_writed_checked,"%Ddr%Dd",addr,val);
00465         else gen_call_function((void *)&mem_writew_checked,"%Ddr%Dd",addr,val);
00466         dyn_check_bool_exception_al();
00467 }
00468 
00469 #else
00470 
00471 static void dyn_read_intro(DynReg * addr,bool release_addr=true) {
00472         gen_protectflags();
00473 
00474         if (addr->genreg) {
00475                 // addr already in a register
00476                 Bit8u reg_idx=(Bit8u)addr->genreg->index;
00477                 x86gen.regs[X86_REG_ECX]->Clear();
00478                 if (reg_idx!=1) {
00479                         cache_addw(0xc88b+(reg_idx<<8));        //Mov ecx,reg
00480                 }
00481                 x86gen.regs[X86_REG_EAX]->Clear();
00482                 if (release_addr) gen_releasereg(addr);
00483         } else {
00484                 // addr still in memory, directly move into ecx
00485                 x86gen.regs[X86_REG_EAX]->Clear();
00486                 x86gen.regs[X86_REG_ECX]->Clear();
00487                 cache_addw(0x0d8b);             //Mov ecx,[data]
00488                 cache_addd((uintptr_t)addr->data);
00489         }
00490         x86gen.regs[X86_REG_EDX]->Clear();
00491 
00492         cache_addw(0xc18b);             // mov eax,ecx
00493 }
00494 
00495 bool mem_readb_checked_dcx86(PhysPt address) {
00496         return get_tlb_readhandler(address)->readb_checked(address, (Bit8u*)(&core_dyn.readdata));
00497 }
00498 
00499 static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) {
00500         dyn_read_intro(addr,false);
00501 
00502         cache_addw(0xe8c1);             // shr eax,0x0c
00503         cache_addb(0x0c);
00504         cache_addw(0x048b);             // mov eax,paging.tlb.read[eax*TYPE Bit32u]
00505         cache_addb(0x85);
00506         cache_addd((uintptr_t)(&paging.tlb.read[0]));
00507         cache_addw(0xc085);             // test eax,eax
00508         Bit8u* je_loc=gen_create_branch(BR_Z);
00509 
00510 
00511         cache_addw(0x048a);             // mov al,[eax+ecx]
00512         cache_addb(0x08);
00513 
00514         Bit8u* jmp_loc=gen_create_jump();
00515         gen_fill_branch(je_loc);
00516         cache_addb(0x51);               // push ecx
00517         cache_addb(0xe8);
00518         cache_addd((uintptr_t)(&mem_readb_checked_dcx86) - (uintptr_t)cache.pos - (uintptr_t)4);
00519         cache_addw(0xc483);             // add esp,4
00520         cache_addb(0x04);
00521         cache_addw(0x012c);             // sub al,1
00522 
00523         dyn_check_bool_exception_ne();
00524 
00525         cache_addw(0x058a);             //mov al,[]
00526         cache_addd((uintptr_t)(&core_dyn.readdata));
00527 
00528         gen_fill_jump(jmp_loc);
00529 
00530         x86gen.regs[X86_REG_EAX]->notusable=true;
00531         GenReg * genreg=FindDynReg(dst);
00532         x86gen.regs[X86_REG_EAX]->notusable=false;
00533         cache_addw(0xc08a+(genreg->index<<11)+(high?0x2000:0));
00534         dst->flags|=DYNFLG_CHANGED;
00535 }
00536 
00537 static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) {
00538         dyn_read_intro(addr);
00539 
00540         cache_addw(0xe8c1);             // shr eax,0x0c
00541         cache_addb(0x0c);
00542         cache_addw(0x048b);             // mov eax,paging.tlb.read[eax*TYPE Bit32u]
00543         cache_addb(0x85);
00544         cache_addd((uintptr_t)(&paging.tlb.read[0]));
00545         cache_addw(0xc085);             // test eax,eax
00546         Bit8u* je_loc=gen_create_branch(BR_Z);
00547 
00548 
00549         cache_addw(0x048a);             // mov al,[eax+ecx]
00550         cache_addb(0x08);
00551 
00552         Bit8u* jmp_loc=gen_create_jump();
00553         gen_fill_branch(je_loc);
00554         cache_addb(0x51);               // push ecx
00555         cache_addb(0xe8);
00556         cache_addd((uintptr_t)(&mem_readb_checked_dcx86) - (uintptr_t)cache.pos - (uintptr_t)4);
00557         cache_addw(0xc483);             // add esp,4
00558         cache_addb(0x04);
00559         cache_addw(0x012c);             // sub al,1
00560 
00561         dyn_check_bool_exception_ne();
00562 
00563         cache_addw(0x058a);             //mov al,[]
00564         cache_addd((uintptr_t)(&core_dyn.readdata));
00565 
00566         gen_fill_jump(jmp_loc);
00567 
00568         x86gen.regs[X86_REG_EAX]->notusable=true;
00569         GenReg * genreg=FindDynReg(dst);
00570         x86gen.regs[X86_REG_EAX]->notusable=false;
00571         cache_addw(0xc08a+(genreg->index<<11)+(high?0x2000:0));
00572         dst->flags|=DYNFLG_CHANGED;
00573 }
00574 
00575 bool mem_readd_checked_dcx86(PhysPt address) {
00576         if ((address & 0xfff)<0xffd) {
00577                 HostPt tlb_addr=get_tlb_read(address);
00578                 if (tlb_addr) {
00579                         core_dyn.readdata=host_readd(tlb_addr+address);
00580                         return false;
00581                 } else {
00582                         return get_tlb_readhandler(address)->readd_checked(address, &core_dyn.readdata);
00583                 }
00584         } else return mem_unalignedreadd_checked(address, &core_dyn.readdata);
00585 }
00586 
00587 static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) {
00588         if (dword) {
00589                 dyn_read_intro(addr,false);
00590 
00591                 cache_addw(0xe8d1);             // shr eax,0x1
00592                 Bit8u* jb_loc1=gen_create_branch(BR_B);
00593                 cache_addw(0xe8d1);             // shr eax,0x1
00594                 Bit8u* jb_loc2=gen_create_branch(BR_B);
00595                 cache_addw(0xe8c1);             // shr eax,0x0a
00596                 cache_addb(0x0a);
00597                 cache_addw(0x048b);             // mov eax,paging.tlb.read[eax*TYPE Bit32u]
00598                 cache_addb(0x85);
00599                 cache_addd((uintptr_t)(&paging.tlb.read[0]));
00600                 cache_addw(0xc085);             // test eax,eax
00601                 Bit8u* je_loc=gen_create_branch(BR_Z);
00602 
00603                 GenReg * genreg=FindDynReg(dst,true);
00604 
00605                 cache_addw(0x048b+(genreg->index <<(8+3)));             // mov dest,[eax+ecx]
00606                 cache_addb(0x08);
00607 
00608                 Bit8u* jmp_loc=gen_create_jump();
00609                 gen_fill_branch(jb_loc1);
00610                 gen_fill_branch(jb_loc2);
00611                 gen_fill_branch(je_loc);
00612                 cache_addb(0x51);               // push ecx
00613                 cache_addb(0xe8);
00614             cache_addd((uintptr_t)(&mem_readd_checked_dcx86) - (uintptr_t)cache.pos - (uintptr_t)4);
00615                 cache_addw(0xc483);             // add esp,4
00616                 cache_addb(0x04);
00617                 cache_addw(0x012c);             // sub al,1
00618 
00619                 dyn_check_bool_exception_ne();
00620 
00621                 gen_mov_host(&core_dyn.readdata,dst,4);
00622                 dst->flags|=DYNFLG_CHANGED;
00623 
00624                 gen_fill_jump(jmp_loc);
00625         } else {
00626                 gen_protectflags();
00627                 gen_call_function((void *)&mem_readw_checked,"%Dd%Id",addr,&core_dyn.readdata);
00628                 dyn_check_bool_exception_al();
00629                 gen_mov_host(&core_dyn.readdata,dst,2);
00630         }
00631 }
00632 
00633 static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) {
00634         if (dword) {
00635                 dyn_read_intro(addr);
00636 
00637                 cache_addw(0xe8d1);             // shr eax,0x1
00638                 Bit8u* jb_loc1=gen_create_branch(BR_B);
00639                 cache_addw(0xe8d1);             // shr eax,0x1
00640                 Bit8u* jb_loc2=gen_create_branch(BR_B);
00641                 cache_addw(0xe8c1);             // shr eax,0x0a
00642                 cache_addb(0x0a);
00643                 cache_addw(0x048b);             // mov eax,paging.tlb.read[eax*TYPE Bit32u]
00644                 cache_addb(0x85);
00645                 cache_addd((uintptr_t)(&paging.tlb.read[0]));
00646                 cache_addw(0xc085);             // test eax,eax
00647                 Bit8u* je_loc=gen_create_branch(BR_Z);
00648 
00649                 GenReg * genreg=FindDynReg(dst,true);
00650 
00651                 cache_addw(0x048b+(genreg->index <<(8+3)));             // mov dest,[eax+ecx]
00652                 cache_addb(0x08);
00653 
00654                 Bit8u* jmp_loc=gen_create_jump();
00655                 gen_fill_branch(jb_loc1);
00656                 gen_fill_branch(jb_loc2);
00657                 gen_fill_branch(je_loc);
00658                 cache_addb(0x51);               // push ecx
00659                 cache_addb(0xe8);
00660             cache_addd((uintptr_t)(&mem_readd_checked_dcx86) - (uintptr_t)cache.pos - (uintptr_t)4);
00661                 cache_addw(0xc483);             // add esp,4
00662                 cache_addb(0x04);
00663                 cache_addw(0x012c);             // sub al,1
00664 
00665                 dyn_check_bool_exception_ne();
00666 
00667                 gen_mov_host(&core_dyn.readdata,dst,4);
00668                 dst->flags|=DYNFLG_CHANGED;
00669 
00670                 gen_fill_jump(jmp_loc);
00671         } else {
00672                 gen_protectflags();
00673                 gen_call_function((void *)&mem_readw_checked,"%Ddr%Id",addr,&core_dyn.readdata);
00674                 dyn_check_bool_exception_al();
00675                 gen_mov_host(&core_dyn.readdata,dst,2);
00676         }
00677 }
00678 
00679 static void dyn_write_intro(DynReg * addr,bool release_addr=true) {
00680         gen_protectflags();
00681 
00682         if (addr->genreg) {
00683                 // addr in a register
00684                 Bit8u reg_idx_addr=(Bit8u)addr->genreg->index;
00685 
00686                 x86gen.regs[X86_REG_EAX]->Clear();
00687                 x86gen.regs[X86_REG_EAX]->notusable=true;
00688                 x86gen.regs[X86_REG_ECX]->Clear();
00689                 x86gen.regs[X86_REG_ECX]->notusable=true;
00690 
00691                 if (reg_idx_addr) {
00692                         // addr!=eax
00693                         cache_addb(0x8b);               //Mov eax,reg
00694                         cache_addb(0xc0+reg_idx_addr);
00695                 }
00696                 if (release_addr) gen_releasereg(addr);
00697         } else {
00698                 // addr still in memory, directly move into eax
00699                 x86gen.regs[X86_REG_EAX]->Clear();
00700                 x86gen.regs[X86_REG_EAX]->notusable=true;
00701                 x86gen.regs[X86_REG_ECX]->Clear();
00702                 x86gen.regs[X86_REG_ECX]->notusable=true;
00703                 cache_addb(0xa1);               //Mov eax,[data]
00704                 cache_addd((uintptr_t)addr->data);
00705         }
00706 
00707         cache_addw(0xc88b);             // mov ecx,eax
00708 }
00709 
00710 static void dyn_write_byte(DynReg * addr,DynReg * val,bool high) {
00711         dyn_write_intro(addr,false);
00712 
00713         GenReg * genreg=FindDynReg(val);
00714         cache_addw(0xe9c1);             // shr ecx,0x0c
00715         cache_addb(0x0c);
00716         cache_addw(0x0c8b);             // mov ecx,paging.tlb.read[ecx*TYPE Bit32u]
00717         cache_addb(0x8d);
00718         cache_addd((uintptr_t)(&paging.tlb.write[0]));
00719         cache_addw(0xc985);             // test ecx,ecx
00720         Bit8u* je_loc=gen_create_branch(BR_Z);
00721 
00722         cache_addw(0x0488+(genreg->index<<11)+(high?0x2000:0));         // mov [eax+ecx],reg
00723         cache_addb(0x08);
00724 
00725         Bit8u* jmp_loc=gen_create_jump();
00726         gen_fill_branch(je_loc);
00727 
00728         if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8));
00729         cache_addb(0x52);       // push edx
00730         cache_addb(0x50+genreg->index);
00731         cache_addb(0x50);       // push eax
00732         if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8));
00733         cache_addb(0xe8);
00734         cache_addd((uintptr_t)(&mem_writeb_checked) - (uintptr_t)cache.pos - (uintptr_t)4);
00735         cache_addw(0xc483);             // add esp,8
00736         cache_addb(0x08);
00737         cache_addw(0x012c);             // sub al,1
00738         cache_addb(0x5a);               // pop edx
00739 
00740         // Restore registers to be used again
00741         x86gen.regs[X86_REG_EAX]->notusable=false;
00742         x86gen.regs[X86_REG_ECX]->notusable=false;
00743 
00744         dyn_check_bool_exception_ne();
00745 
00746         gen_fill_jump(jmp_loc);
00747 }
00748 
00749 static void dyn_write_byte_release(DynReg * addr,DynReg * val,bool high) {
00750         dyn_write_intro(addr);
00751 
00752         GenReg * genreg=FindDynReg(val);
00753         cache_addw(0xe9c1);             // shr ecx,0x0c
00754         cache_addb(0x0c);
00755         cache_addw(0x0c8b);             // mov ecx,paging.tlb.read[ecx*TYPE Bit32u]
00756         cache_addb(0x8d);
00757         cache_addd((uintptr_t)(&paging.tlb.write[0]));
00758         cache_addw(0xc985);             // test ecx,ecx
00759         Bit8u* je_loc=gen_create_branch(BR_Z);
00760 
00761         cache_addw(0x0488+(genreg->index<<11)+(high?0x2000:0));         // mov [eax+ecx],reg
00762         cache_addb(0x08);
00763 
00764         Bit8u* jmp_loc=gen_create_jump();
00765         gen_fill_branch(je_loc);
00766 
00767         cache_addb(0x52);       // push edx
00768         if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8));
00769         cache_addb(0x50+genreg->index);
00770         cache_addb(0x50);       // push eax
00771         if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8));
00772         cache_addb(0xe8);
00773         cache_addd((uintptr_t)(&mem_writeb_checked) - (uintptr_t)cache.pos - (uintptr_t)4);
00774         cache_addw(0xc483);             // add esp,8
00775         cache_addb(0x08);
00776         cache_addw(0x012c);             // sub al,1
00777         cache_addb(0x5a);               // pop edx
00778 
00779         // Restore registers to be used again
00780         x86gen.regs[X86_REG_EAX]->notusable=false;
00781         x86gen.regs[X86_REG_ECX]->notusable=false;
00782 
00783         dyn_check_bool_exception_ne();
00784 
00785         gen_fill_jump(jmp_loc);
00786 }
00787 
00788 static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) {
00789         if (dword) {
00790                 dyn_write_intro(addr,false);
00791 
00792                 GenReg * genreg=FindDynReg(val);
00793                 cache_addw(0xe9d1);             // shr ecx,0x1
00794                 Bit8u* jb_loc1=gen_create_branch(BR_B);
00795                 cache_addw(0xe9d1);             // shr ecx,0x1
00796                 Bit8u* jb_loc2=gen_create_branch(BR_B);
00797                 cache_addw(0xe9c1);             // shr ecx,0x0a
00798                 cache_addb(0x0a);
00799                 cache_addw(0x0c8b);             // mov ecx,paging.tlb.read[ecx*TYPE Bit32u]
00800                 cache_addb(0x8d);
00801                 cache_addd((uintptr_t)(&paging.tlb.write[0]));
00802                 cache_addw(0xc985);             // test ecx,ecx
00803                 Bit8u* je_loc=gen_create_branch(BR_Z);
00804 
00805                 cache_addw(0x0489+(genreg->index <<(8+3)));             // mov [eax+ecx],reg
00806                 cache_addb(0x08);
00807 
00808                 Bit8u* jmp_loc=gen_create_jump();
00809                 gen_fill_branch(jb_loc1);
00810                 gen_fill_branch(jb_loc2);
00811                 gen_fill_branch(je_loc);
00812 
00813                 cache_addb(0x52);       // push edx
00814                 cache_addb(0x50+genreg->index);
00815                 cache_addb(0x50);       // push eax
00816                 cache_addb(0xe8);
00817             cache_addd((uintptr_t)(&mem_writed_checked) - (uintptr_t)cache.pos - (uintptr_t)4);
00818                 cache_addw(0xc483);             // add esp,8
00819                 cache_addb(0x08);
00820                 cache_addw(0x012c);             // sub al,1
00821                 cache_addb(0x5a);               // pop edx
00822 
00823                 // Restore registers to be used again
00824                 x86gen.regs[X86_REG_EAX]->notusable=false;
00825                 x86gen.regs[X86_REG_ECX]->notusable=false;
00826 
00827                 dyn_check_bool_exception_ne();
00828 
00829                 gen_fill_jump(jmp_loc);
00830         } else {
00831                 gen_protectflags();
00832                 gen_call_function((void *)&mem_writew_checked,"%Dd%Dd",addr,val);
00833                 dyn_check_bool_exception_al();
00834         }
00835 }
00836 
00837 static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) {
00838         if (dword) {
00839                 dyn_write_intro(addr);
00840 
00841                 GenReg * genreg=FindDynReg(val);
00842                 cache_addw(0xe9d1);             // shr ecx,0x1
00843                 Bit8u* jb_loc1=gen_create_branch(BR_B);
00844                 cache_addw(0xe9d1);             // shr ecx,0x1
00845                 Bit8u* jb_loc2=gen_create_branch(BR_B);
00846                 cache_addw(0xe9c1);             // shr ecx,0x0a
00847                 cache_addb(0x0a);
00848                 cache_addw(0x0c8b);             // mov ecx,paging.tlb.read[ecx*TYPE Bit32u]
00849                 cache_addb(0x8d);
00850                 cache_addd((uintptr_t)(&paging.tlb.write[0]));
00851                 cache_addw(0xc985);             // test ecx,ecx
00852                 Bit8u* je_loc=gen_create_branch(BR_Z);
00853 
00854                 cache_addw(0x0489+(genreg->index <<(8+3)));             // mov [eax+ecx],reg
00855                 cache_addb(0x08);
00856 
00857                 Bit8u* jmp_loc=gen_create_jump();
00858                 gen_fill_branch(jb_loc1);
00859                 gen_fill_branch(jb_loc2);
00860                 gen_fill_branch(je_loc);
00861 
00862                 cache_addb(0x52);       // push edx
00863                 cache_addb(0x50+genreg->index);
00864                 cache_addb(0x50);       // push eax
00865                 cache_addb(0xe8);
00866             cache_addd((uintptr_t)(&mem_writed_checked) - (uintptr_t)cache.pos - (uintptr_t)4);
00867                 cache_addw(0xc483);             // add esp,8
00868                 cache_addb(0x08);
00869                 cache_addw(0x012c);             // sub al,1
00870                 cache_addb(0x5a);               // pop edx
00871 
00872                 // Restore registers to be used again
00873                 x86gen.regs[X86_REG_EAX]->notusable=false;
00874                 x86gen.regs[X86_REG_ECX]->notusable=false;
00875 
00876                 dyn_check_bool_exception_ne();
00877 
00878                 gen_fill_jump(jmp_loc);
00879         } else {
00880                 gen_protectflags();
00881                 gen_call_function((void *)&mem_writew_checked,"%Ddr%Dd",addr,val);
00882                 dyn_check_bool_exception_al();
00883         }
00884 }
00885 
00886 #endif
00887 
00888 static void dyn_push_unchecked(DynReg * dynreg) {
00889         gen_protectflags();
00890         gen_lea(DREG(STACK),DREG(ESP),0,0,decode.big_op?(-4):(-2));
00891         gen_dop_word_var(DOP_AND,true,DREG(STACK),&cpu.stack.mask);
00892         gen_dop_word_var(DOP_AND,true,DREG(ESP),&cpu.stack.notmask);
00893         gen_dop_word(DOP_OR,true,DREG(ESP),DREG(STACK));
00894         gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS));
00895         if (decode.big_op) {
00896                 gen_call_function((void *)&mem_writed,"%Drd%Dd",DREG(STACK),dynreg);
00897         } else {
00898                 //Can just push the whole 32-bit word as operand
00899                 gen_call_function((void *)&mem_writew,"%Drd%Dd",DREG(STACK),dynreg);
00900         }
00901 }
00902 
00903 static void dyn_push(DynReg * dynreg) {
00904         gen_protectflags();
00905         gen_lea(DREG(STACK),DREG(ESP),0,0,decode.big_op?(-4):(-2));
00906         gen_dop_word(DOP_MOV,true,DREG(NEWESP),DREG(ESP));
00907         gen_dop_word_var(DOP_AND,true,DREG(STACK),&cpu.stack.mask);
00908         gen_dop_word_var(DOP_AND,true,DREG(NEWESP),&cpu.stack.notmask);
00909         gen_dop_word(DOP_OR,true,DREG(NEWESP),DREG(STACK));
00910         gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS));
00911         if (decode.big_op) {
00912                 gen_call_function((void *)&mem_writed_checked,"%Drd%Dd",DREG(STACK),dynreg);
00913         } else {
00914                 //Can just push the whole 32-bit word as operand
00915                 gen_call_function((void *)&mem_writew_checked,"%Drd%Dd",DREG(STACK),dynreg);
00916         }
00917         dyn_check_bool_exception_al();
00918         /* everything was ok, change register now */
00919         gen_dop_word(DOP_MOV,true,DREG(ESP),DREG(NEWESP));
00920         gen_releasereg(DREG(NEWESP));
00921 }
00922 
00923 static void dyn_pop(DynReg * dynreg,bool checked=true) {
00924         gen_protectflags();
00925         gen_dop_word(DOP_MOV,true,DREG(STACK),DREG(ESP));
00926         gen_dop_word_var(DOP_AND,true,DREG(STACK),&cpu.stack.mask);
00927         gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS));
00928         if (checked) {
00929                 if (decode.big_op) {
00930                         gen_call_function((void *)&mem_readd_checked,"%Drd%Id",DREG(STACK),&core_dyn.readdata);
00931                 } else {
00932                         gen_call_function((void *)&mem_readw_checked,"%Drd%Id",DREG(STACK),&core_dyn.readdata);
00933                 }
00934                 dyn_check_bool_exception_al();
00935                 gen_mov_host(&core_dyn.readdata,dynreg,decode.big_op?4:2);
00936         } else {
00937                 if (decode.big_op) {
00938                         gen_call_function((void *)&mem_readd,"%Rd%Drd",dynreg,DREG(STACK));
00939                 } else {
00940                         gen_call_function((void *)&mem_readw,"%Rw%Drd",dynreg,DREG(STACK));
00941                 }
00942         }
00943         if (dynreg!=DREG(ESP)) {
00944                 gen_lea(DREG(STACK),DREG(ESP),0,0,decode.big_op?4:2);
00945                 gen_dop_word_var(DOP_AND,true,DREG(STACK),&cpu.stack.mask);
00946                 gen_dop_word_var(DOP_AND,true,DREG(ESP),&cpu.stack.notmask);
00947                 gen_dop_word(DOP_OR,true,DREG(ESP),DREG(STACK));
00948         }
00949 }
00950 
00951 static INLINE void dyn_get_modrm(void) {
00952         decode.modrm.val=decode_fetchb();
00953         decode.modrm.mod=(decode.modrm.val >> 6) & 3;
00954         decode.modrm.reg=(decode.modrm.val >> 3) & 7;
00955         decode.modrm.rm=(decode.modrm.val & 7);
00956 }
00957 
00958 static void dyn_fill_ea(bool addseg=true, DynReg * reg_ea=DREG(EA)) {
00959         DynReg * segbase;
00960         if (!decode.big_addr) {
00961                 Bits imm;
00962                 switch (decode.modrm.mod) {
00963                         case 1:imm=(Bit8s)decode_fetchb();break;
00964                         case 2:imm=(Bit16s)decode_fetchw();break;
00965                         default:imm=0;break;
00966                 }
00967                 DynReg * extend_src=reg_ea;
00968                 switch (decode.modrm.rm) {
00969                 case 0:/* BX+SI */
00970                         gen_lea(reg_ea,DREG(EBX),DREG(ESI),0,imm);
00971                         segbase=DREG(DS);
00972                         break;
00973                 case 1:/* BX+DI */
00974                         gen_lea(reg_ea,DREG(EBX),DREG(EDI),0,imm);
00975                         segbase=DREG(DS);
00976                         break;
00977                 case 2:/* BP+SI */
00978                         gen_lea(reg_ea,DREG(EBP),DREG(ESI),0,imm);
00979                         segbase=DREG(SS);
00980                         break;
00981                 case 3:/* BP+DI */
00982                         gen_lea(reg_ea,DREG(EBP),DREG(EDI),0,imm);
00983                         segbase=DREG(SS);
00984                         break;
00985                 case 4:/* SI */
00986                         if (imm) gen_lea(reg_ea,DREG(ESI),0,0,imm);
00987                         else extend_src=DREG(ESI);
00988                         segbase=DREG(DS);
00989                         break;
00990                 case 5:/* DI */
00991                         if (imm) gen_lea(reg_ea,DREG(EDI),0,0,imm);
00992                         else extend_src=DREG(EDI);
00993                         segbase=DREG(DS);
00994                         break;
00995                 case 6:/* imm/BP */
00996                         if (!decode.modrm.mod) {
00997                                 imm=decode_fetchw();
00998                 gen_dop_word_imm(DOP_MOV,true,reg_ea,imm);
00999                                 segbase=DREG(DS);
01000                                 goto skip_extend_word;
01001                         } else {
01002                                 gen_lea(reg_ea,DREG(EBP),0,0,imm);
01003                                 segbase=DREG(SS);
01004                         }
01005                         break;
01006                 case 7: /* BX */
01007                         if (imm) gen_lea(reg_ea,DREG(EBX),0,0,imm);
01008                         else extend_src=DREG(EBX);
01009                         segbase=DREG(DS);
01010                         break;
01011                 }
01012                 gen_extend_word(false,reg_ea,extend_src);
01013 skip_extend_word:
01014                 if (addseg) {
01015                         gen_lea(reg_ea,reg_ea,decode.segprefix ? decode.segprefix : segbase,0,0);
01016                 }
01017         } else {
01018                 Bits imm=0;
01019                 DynReg * base=0;DynReg * scaled=0;Bitu scale=0;
01020                 switch (decode.modrm.rm) {
01021                 case 0:base=DREG(EAX);segbase=DREG(DS);break;
01022                 case 1:base=DREG(ECX);segbase=DREG(DS);break;
01023                 case 2:base=DREG(EDX);segbase=DREG(DS);break;
01024                 case 3:base=DREG(EBX);segbase=DREG(DS);break;
01025                 case 4: /* SIB */
01026                         {
01027                                 Bitu sib=decode_fetchb();
01028                                 static DynReg * scaledtable[8]={
01029                                         DREG(EAX),DREG(ECX),DREG(EDX),DREG(EBX),
01030                                                         0,DREG(EBP),DREG(ESI),DREG(EDI),
01031                                 };
01032                                 scaled=scaledtable[(sib >> 3) &7];
01033                                 scale=(sib >> 6);
01034                                 switch (sib & 7) {
01035                                 case 0:base=DREG(EAX);segbase=DREG(DS);break;
01036                                 case 1:base=DREG(ECX);segbase=DREG(DS);break;
01037                                 case 2:base=DREG(EDX);segbase=DREG(DS);break;
01038                                 case 3:base=DREG(EBX);segbase=DREG(DS);break;
01039                                 case 4:base=DREG(ESP);segbase=DREG(SS);break;
01040                                 case 5:
01041                                         if (decode.modrm.mod) {
01042                                                 base=DREG(EBP);segbase=DREG(SS);
01043                                         } else {
01044                                                 segbase=DREG(DS);
01045                                                 Bitu val;
01046                                                 if (decode_fetchd_imm(val)) {
01047                                                         gen_mov_host((void*)val,DREG(EA),4);
01048                                                         if (!addseg) {
01049                                                                 gen_lea(reg_ea,DREG(EA),scaled,scale,0);
01050                                                         } else {
01051                                                                 DynReg** seg = decode.segprefix ? &decode.segprefix : &segbase;
01052                                                                 gen_lea(DREG(EA),DREG(EA),scaled,scale,0);
01053                                                                 gen_lea(reg_ea,DREG(EA),*seg,0,0);
01054                                                         }
01055                                                         return;
01056                                                 }
01057                                                 imm=(Bit32s)val;
01058                                         }
01059                                         break;
01060                                 case 6:base=DREG(ESI);segbase=DREG(DS);break;
01061                                 case 7:base=DREG(EDI);segbase=DREG(DS);break;
01062                                 }
01063                         }       
01064                         break;  /* SIB Break */
01065                 case 5:
01066                         if (decode.modrm.mod) {
01067                                 base=DREG(EBP);segbase=DREG(SS);
01068                         } else {
01069                                 imm=(Bit32s)decode_fetchd();segbase=DREG(DS);
01070                         }
01071                         break;
01072                 case 6:base=DREG(ESI);segbase=DREG(DS);break;
01073                 case 7:base=DREG(EDI);segbase=DREG(DS);break;
01074                 }
01075                 switch (decode.modrm.mod) {
01076                 case 1:imm=(Bit8s)decode_fetchb();break;
01077                 case 2: {
01078                         Bitu val;
01079                         if (decode_fetchd_imm(val)) {
01080                                 gen_mov_host((void*)val,DREG(EA),4);
01081                                 if (!addseg) {
01082                                         gen_lea(DREG(EA),DREG(EA),scaled,scale,0);
01083                                         gen_lea(reg_ea,DREG(EA),base,0,0);
01084                                 } else {
01085                                         DynReg** seg = decode.segprefix ? &decode.segprefix : &segbase;
01086                                         if (!base) {
01087                                                 gen_lea(DREG(EA),DREG(EA),scaled,scale,0);
01088                                                 gen_lea(reg_ea,DREG(EA),*seg,0,0);
01089                                         } else if (!scaled) {
01090                                                 gen_lea(DREG(EA),DREG(EA),*seg,0,0);
01091                                                 gen_lea(reg_ea,DREG(EA),base,0,0);
01092                                         } else {
01093                                                 gen_lea(DREG(EA),DREG(EA),scaled,scale,0);
01094                                                 gen_lea(DREG(EA),DREG(EA),base,0,0);
01095                                                 gen_lea(reg_ea,DREG(EA),decode.segprefix ? decode.segprefix : segbase,0,0);
01096                                         }
01097                                 }
01098                                 return;
01099                         }
01100                         
01101                         imm=(Bit32s)val;
01102                         break;
01103                         }
01104                 }
01105                 if (!addseg) {
01106                         gen_lea(reg_ea,base,scaled,scale,imm);
01107                 } else {
01108                         DynReg** seg = decode.segprefix ? &decode.segprefix : &segbase;
01109                         if (!base) gen_lea(reg_ea,*seg,scaled,scale,imm);
01110                         else if (!scaled) gen_lea(reg_ea,base,*seg,0,imm);
01111                         else {
01112                                 gen_lea(DREG(EA),base,scaled,scale,imm);
01113                                 gen_lea(reg_ea,DREG(EA),decode.segprefix ? decode.segprefix : segbase,0,0);
01114                         }
01115                 }
01116         }
01117 }
01118 
01119 
01120 static void dyn_dop_word_imm(DualOps op,bool dword,DynReg * dr1) {
01121         Bitu val;
01122         if (dword) {
01123                 if (decode_fetchd_imm(val)) {
01124                         gen_dop_word_imm_mem(op,true,dr1,(void*)val);
01125                         return;
01126                 }
01127         } else {
01128                 if (decode_fetchw_imm(val)) {
01129                         gen_dop_word_imm_mem(op,false,dr1,(void*)val);
01130                         return;
01131                 }
01132         }
01133         gen_dop_word_imm(op,dword,dr1,val);
01134 }
01135 
01136 static void dyn_dop_byte_imm(DualOps op,DynReg * dr1,Bit8u di1) {
01137         Bitu val;
01138         if (decode_fetchb_imm(val)) {
01139                 gen_dop_byte_imm_mem(op,dr1,di1,(void*)val);
01140         } else {
01141                 gen_dop_byte_imm(op,dr1,di1,(Bit8u)val);
01142         }
01143 }
01144 
01145 
01146 #include "helpers.h"
01147 #include "string.h"
01148 
01149 
01150 static void dyn_dop_ebgb(DualOps op) {
01151         dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];
01152         if (decode.modrm.mod<3) {
01153                 dyn_fill_ea();
01154                 if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true);
01155                 dyn_read_byte(DREG(EA),DREG(TMPB),false);
01156                 if (op<=DOP_TEST) {
01157                         if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
01158                         else set_skipflags(false);
01159                 }
01160                 gen_dop_byte(op,DREG(TMPB),0,rm_reg,decode.modrm.reg&4);
01161                 if (op!=DOP_CMP) dyn_write_byte_release(DREG(EA),DREG(TMPB),false);
01162                 else gen_releasereg(DREG(EA));
01163                 gen_releasereg(DREG(TMPB));
01164         } else {
01165                 if (op<=DOP_TEST) {
01166                         if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
01167                         else gen_discardflags();
01168                 }
01169                 gen_dop_byte(op,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,rm_reg,decode.modrm.reg&4);
01170         }
01171 }
01172 
01173 
01174 static void dyn_dop_gbeb(DualOps op) {
01175         dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];
01176         if (decode.modrm.mod<3) {
01177                 dyn_fill_ea();
01178                 if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true);
01179                 dyn_read_byte_release(DREG(EA),DREG(TMPB),false);
01180                 if (op<=DOP_TEST) {
01181                         if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
01182                         else set_skipflags(false);
01183                 }
01184                 gen_dop_byte(op,rm_reg,decode.modrm.reg&4,DREG(TMPB),0);
01185                 gen_releasereg(DREG(TMPB));
01186         } else {
01187                 if (op<=DOP_TEST) {
01188                         if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
01189                         else gen_discardflags();
01190                 }
01191                 gen_dop_byte(op,rm_reg,decode.modrm.reg&4,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
01192         }
01193 }
01194 
01195 static void dyn_mov_ebib(void) {
01196         dyn_get_modrm();
01197         if (decode.modrm.mod<3) {
01198                 dyn_fill_ea();
01199                 gen_call_write(DREG(EA),decode_fetchb(),1);
01200                 dyn_check_bool_exception_al();
01201         } else {
01202                 gen_dop_byte_imm(DOP_MOV,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,decode_fetchb());
01203         }
01204 }
01205 
01206 static void dyn_mov_ebgb(void) {
01207         dyn_get_modrm();
01208         DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];Bitu rm_regi=decode.modrm.reg&4;
01209         if (decode.modrm.mod<3) {
01210                 dyn_fill_ea();
01211                 dyn_write_byte_release(DREG(EA),rm_reg,rm_regi==4);
01212         } else {
01213                 gen_dop_byte(DOP_MOV,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,rm_reg,rm_regi);
01214         }
01215 }
01216 
01217 static void dyn_mov_gbeb(void) {
01218         dyn_get_modrm();
01219         DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];Bitu rm_regi=decode.modrm.reg&4;
01220         if (decode.modrm.mod<3) {
01221                 dyn_fill_ea();
01222                 dyn_read_byte_release(DREG(EA),rm_reg,rm_regi);
01223         } else {
01224                 gen_dop_byte(DOP_MOV,rm_reg,rm_regi,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
01225         }
01226 }
01227 
01228 static void dyn_dop_evgv(DualOps op) {
01229         dyn_get_modrm();
01230         DynReg * rm_reg=&DynRegs[decode.modrm.reg];
01231         if (decode.modrm.mod<3) {
01232                 dyn_fill_ea();
01233                 if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true);
01234                 dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op);
01235                 if (op<=DOP_TEST) {
01236                         if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
01237                         else set_skipflags(false);
01238                 }
01239                 gen_dop_word(op,decode.big_op,DREG(TMPW),rm_reg);
01240                 if (op!=DOP_CMP) dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op);
01241                 else gen_releasereg(DREG(EA));
01242                 gen_releasereg(DREG(TMPW));
01243         } else {
01244                 if (op<=DOP_TEST) {
01245                         if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
01246                         else gen_discardflags();
01247                 }
01248                 gen_dop_word(op,decode.big_op,&DynRegs[decode.modrm.rm],rm_reg);
01249         }
01250 }
01251 
01252 static void dyn_imul_gvev(Bitu immsize) {
01253         dyn_get_modrm();DynReg * src;
01254         DynReg * rm_reg=&DynRegs[decode.modrm.reg];
01255         if (decode.modrm.mod<3) {
01256                 dyn_fill_ea();dyn_read_word_release(DREG(EA),DREG(TMPW),decode.big_op);
01257                 src=DREG(TMPW);
01258         } else {
01259                 src=&DynRegs[decode.modrm.rm];
01260         }
01261         gen_needflags();
01262         switch (immsize) {
01263         case 0:gen_imul_word(decode.big_op,rm_reg,src);break;
01264         case 1:gen_imul_word_imm(decode.big_op,rm_reg,src,(Bit8s)decode_fetchb());break;
01265         case 2:gen_imul_word_imm(decode.big_op,rm_reg,src,(Bit16s)decode_fetchw());break;
01266         case 4:gen_imul_word_imm(decode.big_op,rm_reg,src,(Bit32s)decode_fetchd());break;
01267         }
01268         gen_releasereg(DREG(TMPW));
01269 }
01270 
01271 static void dyn_dop_gvev(DualOps op) {
01272         dyn_get_modrm();
01273         DynReg * rm_reg=&DynRegs[decode.modrm.reg];
01274         if (decode.modrm.mod<3) {
01275                 dyn_fill_ea();
01276                 if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true);
01277                 dyn_read_word_release(DREG(EA),DREG(TMPW),decode.big_op);
01278                 if (op<=DOP_TEST) {
01279                         if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
01280                         else set_skipflags(false);
01281                 }
01282                 gen_dop_word(op,decode.big_op,rm_reg,DREG(TMPW));
01283                 gen_releasereg(DREG(TMPW));
01284         } else {
01285                 if (op<=DOP_TEST) {
01286                         if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
01287                         else gen_discardflags();
01288                 }
01289                 gen_dop_word(op,decode.big_op,rm_reg,&DynRegs[decode.modrm.rm]);
01290         }
01291 }
01292 
01293 static void dyn_mov_evgv(void) {
01294         dyn_get_modrm();
01295         DynReg * rm_reg=&DynRegs[decode.modrm.reg];
01296         if (decode.modrm.mod<3) {
01297                 dyn_fill_ea();
01298                 dyn_write_word_release(DREG(EA),rm_reg,decode.big_op);
01299         } else {
01300                 gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],rm_reg);
01301         }
01302 }
01303 
01304 static void dyn_mov_gvev(void) {
01305         dyn_get_modrm();
01306         DynReg * rm_reg=&DynRegs[decode.modrm.reg];
01307         if (decode.modrm.mod<3) {
01308                 dyn_fill_ea();
01309                 dyn_read_word_release(DREG(EA),rm_reg,decode.big_op);
01310         } else {
01311                 gen_dop_word(DOP_MOV,decode.big_op,rm_reg,&DynRegs[decode.modrm.rm]);
01312         }
01313 }
01314 static void dyn_mov_eviv(void) {
01315         dyn_get_modrm();
01316         if (decode.modrm.mod<3) {
01317                 dyn_fill_ea();
01318                 gen_call_write(DREG(EA),decode.big_op ? decode_fetchd() : decode_fetchw(),decode.big_op?4:2);
01319                 dyn_check_bool_exception_al();
01320         } else {
01321                 gen_dop_word_imm(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],decode.big_op ? decode_fetchd() : decode_fetchw());
01322         }
01323 }
01324 
01325 static void dyn_mov_ev_gb(bool sign) {
01326         dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg];
01327         if (decode.modrm.mod<3) {
01328                 dyn_fill_ea();
01329                 dyn_read_byte_release(DREG(EA),DREG(TMPB),false);
01330                 gen_extend_byte(sign,decode.big_op,rm_reg,DREG(TMPB),0);
01331                 gen_releasereg(DREG(TMPB));
01332         } else {
01333                 gen_extend_byte(sign,decode.big_op,rm_reg,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
01334         }
01335 }
01336 
01337 static void dyn_mov_ev_gw(bool sign) {
01338         if (!decode.big_op) {
01339                 dyn_mov_gvev();
01340                 return;
01341         }
01342         dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg];
01343         if (decode.modrm.mod<3) {
01344                 dyn_fill_ea();
01345                 dyn_read_word_release(DREG(EA),DREG(TMPW),false);
01346                 gen_extend_word(sign,rm_reg,DREG(TMPW));
01347                 gen_releasereg(DREG(TMPW));
01348         } else {
01349                 gen_extend_word(sign,rm_reg,&DynRegs[decode.modrm.rm]);
01350         }
01351 }
01352 
01353 static void dyn_cmpxchg_evgv(void) {
01354         dyn_get_modrm();
01355         DynReg * rm_reg=&DynRegs[decode.modrm.reg];
01356         gen_protectflags();
01357         if (decode.modrm.mod<3) {
01358                 gen_releasereg(DREG(EAX));
01359                 gen_releasereg(DREG(TMPB));
01360                 gen_releasereg(rm_reg);
01361 
01362                 dyn_fill_ea();
01363                 dyn_read_word(DREG(EA),DREG(TMPB),decode.big_op);
01364                 gen_dop_word(DOP_CMP,decode.big_op,DREG(EAX),DREG(TMPB));
01365                 Bit8u * branch=gen_create_branch(BR_NZ);
01366 
01367                 // eax==mem -> mem:=rm_reg
01368                 dyn_write_word_release(DREG(EA),rm_reg,decode.big_op);
01369                 gen_setzeroflag();
01370                 gen_releasereg(DREG(EAX));
01371                 gen_releasereg(DREG(TMPB));
01372                 gen_releasereg(rm_reg);
01373 
01374                 Bit8u * jump=gen_create_jump();
01375 
01376                 gen_fill_branch(branch);
01377                 // eax!=mem -> eax:=mem
01378                 dyn_write_word_release(DREG(EA),DREG(TMPB),decode.big_op);      // cmpxchg always issues write
01379                 gen_dop_word(DOP_MOV,decode.big_op,DREG(EAX),DREG(TMPB));
01380                 gen_clearzeroflag();
01381                 gen_releasereg(DREG(EAX));
01382                 gen_releasereg(DREG(TMPB));
01383                 gen_releasereg(rm_reg);
01384 
01385                 gen_fill_jump(jump);
01386         } else {
01387                 gen_releasereg(DREG(EAX));
01388                 gen_releasereg(&DynRegs[decode.modrm.rm]);
01389                 gen_releasereg(rm_reg);
01390 
01391                 gen_dop_word(DOP_CMP,decode.big_op,DREG(EAX),&DynRegs[decode.modrm.rm]);
01392                 Bit8u * branch=gen_create_branch(BR_NZ);
01393 
01394                 // eax==rm -> rm:=rm_reg
01395                 gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],rm_reg);
01396                 gen_setzeroflag();
01397                 gen_releasereg(DREG(EAX));
01398                 gen_releasereg(&DynRegs[decode.modrm.rm]);
01399                 gen_releasereg(rm_reg);
01400 
01401                 Bit8u * jump=gen_create_jump();
01402 
01403                 gen_fill_branch(branch);
01404                 // eax!=rm -> eax:=rm
01405                 gen_dop_word(DOP_MOV,decode.big_op,DREG(EAX),&DynRegs[decode.modrm.rm]);
01406                 gen_clearzeroflag();
01407                 gen_releasereg(DREG(EAX));
01408                 gen_releasereg(&DynRegs[decode.modrm.rm]);
01409                 gen_releasereg(rm_reg);
01410 
01411                 gen_fill_jump(jump);
01412         }
01413 }
01414 
01415 static void dyn_dshift_ev_gv(bool left,bool immediate) {
01416         dyn_get_modrm();
01417         DynReg * rm_reg=&DynRegs[decode.modrm.reg];
01418         DynReg * ea_reg;
01419         if (decode.modrm.mod<3) {
01420                 dyn_fill_ea();ea_reg=DREG(TMPW);
01421                 dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op);
01422         } else ea_reg=&DynRegs[decode.modrm.rm];
01423         gen_needflags();
01424         if (immediate) gen_dshift_imm(decode.big_op,left,ea_reg,rm_reg,decode_fetchb());
01425         else gen_dshift_cl(decode.big_op,left,ea_reg,rm_reg,DREG(ECX));
01426         if (decode.modrm.mod<3) {
01427                 dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op);
01428                 gen_releasereg(DREG(TMPW));
01429         }
01430 }
01431 
01432 
01433 static DualOps grp1_table[8]={DOP_ADD,DOP_OR,DOP_ADC,DOP_SBB,DOP_AND,DOP_SUB,DOP_XOR,DOP_CMP};
01434 static void dyn_grp1_eb_ib(void) {
01435         dyn_get_modrm();
01436         DualOps op=grp1_table[decode.modrm.reg];
01437         if (decode.modrm.mod<3) {
01438                 dyn_fill_ea();
01439                 if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true);
01440                 dyn_read_byte(DREG(EA),DREG(TMPB),false);
01441                 if (op<=DOP_TEST) {
01442                         if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
01443                         else set_skipflags(false);
01444                 }
01445                 gen_dop_byte_imm(op,DREG(TMPB),0,decode_fetchb());
01446                 if (op!=DOP_CMP) dyn_write_byte_release(DREG(EA),DREG(TMPB),false);
01447                 else gen_releasereg(DREG(EA));
01448                 gen_releasereg(DREG(TMPB));
01449         } else {
01450                 if (op<=DOP_TEST) {
01451                         if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
01452                         else gen_discardflags();
01453                 }
01454                 dyn_dop_byte_imm(op,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
01455         }
01456 }
01457 
01458 static void dyn_grp1_ev_ivx(bool withbyte) {
01459         dyn_get_modrm();
01460         DualOps op=grp1_table[decode.modrm.reg];
01461         if (decode.modrm.mod<3) {
01462                 dyn_fill_ea();
01463                 if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true);
01464                 dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op);
01465                 if (op<=DOP_TEST) {
01466                         if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
01467                         else set_skipflags(false);
01468                 }
01469                 if (!withbyte) {
01470                         dyn_dop_word_imm(op,decode.big_op,DREG(TMPW));
01471                 } else {
01472                         gen_dop_word_imm(op,decode.big_op,DREG(TMPW),(Bit8s)decode_fetchb());
01473                 }
01474                 if (op!=DOP_CMP) dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op);
01475                 else gen_releasereg(DREG(EA));
01476                 gen_releasereg(DREG(TMPW));
01477         } else {
01478                 if (op<=DOP_TEST) {
01479                         if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
01480                         else gen_discardflags();
01481                 }
01482                 if (!withbyte) {
01483                         dyn_dop_word_imm(op,decode.big_op,&DynRegs[decode.modrm.rm]);
01484                 } else {
01485                         gen_dop_word_imm(op,decode.big_op,&DynRegs[decode.modrm.rm],(Bit8s)decode_fetchb());
01486                 }
01487         }
01488 }
01489 
01490 enum grp2_types {
01491         grp2_1,grp2_imm,grp2_cl,
01492 };
01493 
01494 static void dyn_grp2_eb(grp2_types type) {
01495         dyn_get_modrm();DynReg * src;Bit8u src_i;
01496         if (decode.modrm.mod<3) {
01497                 dyn_fill_ea();dyn_read_byte(DREG(EA),DREG(TMPB),false);
01498                 src=DREG(TMPB);
01499                 src_i=0;
01500         } else {
01501                 src=&DynRegs[decode.modrm.rm&3];
01502                 src_i=decode.modrm.rm&4;
01503         }
01504         switch (type) {
01505         case grp2_1:
01506                 /* rotates (first 4 ops) alter cf/of only; shifts (last 4 ops) alter all flags */
01507                 if (decode.modrm.reg < 4) gen_needflags();
01508                 else gen_discardflags();
01509                 gen_shift_byte_imm(decode.modrm.reg,src,src_i,1);
01510                 break;
01511         case grp2_imm: {
01512                 Bit8u imm=decode_fetchb();
01513                 if (imm) {
01514                         /* rotates (first 4 ops) alter cf/of only; shifts (last 4 ops) alter all flags */
01515                         if (decode.modrm.reg < 4) gen_needflags();
01516                         else gen_discardflags();
01517                         gen_shift_byte_imm(decode.modrm.reg,src,src_i,imm);
01518                 } else return;
01519                 }
01520                 break;
01521         case grp2_cl:
01522                 gen_needflags();        /* flags must not be changed on ecx==0 */
01523                 gen_shift_byte_cl (decode.modrm.reg,src,src_i,DREG(ECX));
01524                 break;
01525         }
01526         if (decode.modrm.mod<3) {
01527                 dyn_write_byte_release(DREG(EA),src,false);
01528                 gen_releasereg(src);
01529         }
01530 }
01531 
01532 static void dyn_grp2_ev(grp2_types type) {
01533         dyn_get_modrm();DynReg * src;
01534         if (decode.modrm.mod<3) {
01535                 dyn_fill_ea();dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op);
01536                 src=DREG(TMPW);
01537         } else {
01538                 src=&DynRegs[decode.modrm.rm];
01539         }
01540         switch (type) {
01541         case grp2_1:
01542                 /* rotates (first 4 ops) alter cf/of only; shifts (last 4 ops) alter all flags */
01543                 if (decode.modrm.reg < 4) gen_needflags();
01544                 else gen_discardflags();
01545                 gen_shift_word_imm(decode.modrm.reg,decode.big_op,src,1);
01546                 break;
01547         case grp2_imm: {
01548                 Bitu val;
01549                 if (decode_fetchb_imm(val)) {
01550                         if (decode.modrm.reg < 4) gen_needflags();
01551                         else gen_discardflags();
01552                         gen_load_host((void*)val,DREG(TMPB),1);
01553                         gen_shift_word_cl(decode.modrm.reg,decode.big_op,src,DREG(TMPB));
01554                         gen_releasereg(DREG(TMPB));
01555                         break;
01556                 }
01557                 Bit8u imm=(Bit8u)val;
01558                 if (imm) {
01559                         /* rotates (first 4 ops) alter cf/of only; shifts (last 4 ops) alter all flags */
01560                         if (decode.modrm.reg < 4) gen_needflags();
01561                         else gen_discardflags();
01562                         gen_shift_word_imm(decode.modrm.reg,decode.big_op,src,imm);
01563                 } else return;
01564                 }
01565                 break;
01566         case grp2_cl:
01567                 gen_needflags();        /* flags must not be changed on ecx==0 */
01568                 gen_shift_word_cl (decode.modrm.reg,decode.big_op,src,DREG(ECX));
01569                 break;
01570         }
01571         if (decode.modrm.mod<3) {
01572                 dyn_write_word_release(DREG(EA),src,decode.big_op);
01573                 gen_releasereg(src);
01574         }
01575 }
01576 
01577 static void dyn_grp3_eb(void) {
01578         dyn_get_modrm();DynReg * src;Bit8u src_i;
01579         if (decode.modrm.mod<3) {
01580                 dyn_fill_ea();
01581                 if ((decode.modrm.reg==0) || (decode.modrm.reg==3)) set_skipflags(true);
01582                 dyn_read_byte(DREG(EA),DREG(TMPB),false);
01583                 src=DREG(TMPB);src_i=0;
01584         } else {
01585                 src=&DynRegs[decode.modrm.rm&3];
01586                 src_i=decode.modrm.rm&4;
01587         }
01588         switch (decode.modrm.reg) {
01589         case 0x0:       /* test eb,ib */
01590                 set_skipflags(false);gen_dop_byte_imm(DOP_TEST,src,src_i,decode_fetchb());
01591                 goto skipsave;
01592         case 0x2:       /* NOT Eb */
01593                 gen_sop_byte(SOP_NOT,src,src_i);
01594                 break;
01595         case 0x3:       /* NEG Eb */
01596                 set_skipflags(false);gen_sop_byte(SOP_NEG,src,src_i);
01597                 break;
01598         case 0x4:       /* mul Eb */
01599                 gen_needflags();gen_mul_byte(false,DREG(EAX),src,src_i);
01600                 goto skipsave;
01601         case 0x5:       /* imul Eb */
01602                 gen_needflags();gen_mul_byte(true,DREG(EAX),src,src_i);
01603                 goto skipsave;
01604         case 0x6:       /* div Eb */
01605         case 0x7:       /* idiv Eb */
01606                 /* EAX could be used, so precache it */
01607                 if (decode.modrm.mod==3)
01608                         gen_dop_byte(DOP_MOV,DREG(TMPB),0,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
01609                 gen_releasereg(DREG(EAX));
01610                 gen_call_function((decode.modrm.reg==6) ? (void *)&dyn_helper_divb : (void *)&dyn_helper_idivb,
01611                         "%Rd%Dd",DREG(TMPB),DREG(TMPB));
01612                 dyn_check_bool_exception(DREG(TMPB));
01613                 goto skipsave;
01614         }
01615         /* Save the result if memory op */
01616         if (decode.modrm.mod<3) dyn_write_byte_release(DREG(EA),src,false);
01617 skipsave:
01618         gen_releasereg(DREG(TMPB));gen_releasereg(DREG(EA));
01619 }
01620 
01621 static void dyn_grp3_ev(void) {
01622         dyn_get_modrm();DynReg * src;
01623         if (decode.modrm.mod<3) {
01624                 dyn_fill_ea();src=DREG(TMPW);
01625                 if ((decode.modrm.reg==0) || (decode.modrm.reg==3)) set_skipflags(true);
01626                 dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op);
01627         } else src=&DynRegs[decode.modrm.rm];
01628         switch (decode.modrm.reg) {
01629         case 0x0:       /* test ev,iv */
01630                 set_skipflags(false);gen_dop_word_imm(DOP_TEST,decode.big_op,src,decode.big_op ? decode_fetchd() : decode_fetchw());
01631                 goto skipsave;
01632         case 0x2:       /* NOT Ev */
01633                 gen_sop_word(SOP_NOT,decode.big_op,src);
01634                 break;
01635         case 0x3:       /* NEG Eb */
01636                 set_skipflags(false);gen_sop_word(SOP_NEG,decode.big_op,src);
01637                 break;
01638         case 0x4:       /* mul Eb */
01639                 gen_needflags();gen_mul_word(false,DREG(EAX),DREG(EDX),decode.big_op,src);
01640                 goto skipsave;
01641         case 0x5:       /* imul Eb */
01642                 gen_needflags();gen_mul_word(true,DREG(EAX),DREG(EDX),decode.big_op,src);
01643                 goto skipsave;
01644         case 0x6:       /* div Eb */
01645         case 0x7:       /* idiv Eb */
01646                 /* EAX could be used, so precache it */
01647                 if (decode.modrm.mod==3)
01648                         gen_dop_word(DOP_MOV,decode.big_op,DREG(TMPW),&DynRegs[decode.modrm.rm]);
01649                 gen_releasereg(DREG(EAX));gen_releasereg(DREG(EDX));
01650                 void * func=(decode.modrm.reg==6) ?
01651                         (decode.big_op ? (void *)&dyn_helper_divd : (void *)&dyn_helper_divw) :
01652                         (decode.big_op ? (void *)&dyn_helper_idivd : (void *)&dyn_helper_idivw);
01653                 gen_call_function(func,"%Rd%Dd",DREG(TMPB),DREG(TMPW));
01654                 dyn_check_bool_exception(DREG(TMPB));
01655                 gen_releasereg(DREG(TMPB));
01656                 goto skipsave;
01657         }
01658         /* Save the result if memory op */
01659         if (decode.modrm.mod<3) dyn_write_word_release(DREG(EA),src,decode.big_op);
01660 skipsave:
01661         gen_releasereg(DREG(TMPW));gen_releasereg(DREG(EA));
01662 }
01663 
01664 static void dyn_mov_ev_seg(void) {
01665         dyn_get_modrm();
01666         gen_load_host(&Segs.val[decode.modrm.reg],DREG(TMPW),2);
01667         if (decode.modrm.mod<3) {
01668                 dyn_fill_ea();
01669                 dyn_write_word_release(DREG(EA),DREG(TMPW),false);
01670         } else {
01671                 gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],DREG(TMPW));
01672         }
01673         gen_releasereg(DREG(TMPW));
01674 }
01675 
01676 static void dyn_load_seg(SegNames seg,DynReg * src) {
01677         gen_call_function((void *)&CPU_SetSegGeneral,"%Rd%Id%Drw",DREG(TMPB),seg,src);
01678         dyn_check_bool_exception(DREG(TMPB));
01679         gen_releasereg(DREG(TMPB));
01680         gen_releasereg(&DynRegs[G_ES+seg]);
01681 }
01682 
01683 static void dyn_load_seg_off_ea(SegNames seg) {
01684         if (decode.modrm.mod<3) {
01685                 dyn_fill_ea();
01686                 gen_lea(DREG(TMPB),DREG(EA),0,0,decode.big_op ? 4:2);
01687                 dyn_read_word(DREG(TMPB),DREG(TMPB),false);
01688                 dyn_read_word_release(DREG(EA),DREG(TMPW),decode.big_op);
01689                 dyn_load_seg(seg,DREG(TMPB));gen_releasereg(DREG(TMPB));
01690                 gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.reg],DREG(TMPW));
01691         } else {
01692                 IllegalOption("dyn_load_seg_off_ea");
01693         }
01694 }
01695 
01696 static void dyn_mov_seg_ev(void) {
01697         dyn_get_modrm();
01698         SegNames seg=(SegNames)decode.modrm.reg;
01699         if (GCC_UNLIKELY(seg==cs)) IllegalOption("dyn_mov_seg_ev");
01700         if (decode.modrm.mod<3) {
01701                 dyn_fill_ea();
01702                 dyn_read_word(DREG(EA),DREG(EA),false);
01703                 dyn_load_seg(seg,DREG(EA));
01704                 gen_releasereg(DREG(EA));
01705         } else {
01706                 dyn_load_seg(seg,&DynRegs[decode.modrm.rm]);
01707         }
01708 }
01709 
01710 static void dyn_push_seg(SegNames seg) {
01711         gen_load_host(&Segs.val[seg],DREG(TMPW),2);
01712         dyn_push(DREG(TMPW));
01713         gen_releasereg(DREG(TMPW));
01714 }
01715 
01716 static void dyn_pop_seg(SegNames seg) {
01717         gen_releasereg(DREG(ESP));
01718         gen_call_function((void *)&CPU_PopSeg,"%Rd%Id%Id",DREG(TMPB),seg,decode.big_op);
01719         dyn_check_bool_exception(DREG(TMPB));
01720         gen_releasereg(DREG(TMPB));
01721         gen_releasereg(&DynRegs[G_ES+seg]);
01722         gen_releasereg(DREG(ESP));
01723 }
01724 
01725 static void dyn_pop_ev(void) {
01726         dyn_pop(DREG(TMPW));
01727         dyn_get_modrm();
01728         if (decode.modrm.mod<3) {
01729                 dyn_fill_ea();
01730 //              dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op);
01731                 if (decode.big_op) gen_call_function((void *)&mem_writed_inline,"%Ddr%Dd",DREG(EA),DREG(TMPW));
01732                 else gen_call_function((void *)&mem_writew_inline,"%Ddr%Dd",DREG(EA),DREG(TMPW));
01733         } else {
01734                 gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],DREG(TMPW));
01735         }
01736         gen_releasereg(DREG(TMPW));
01737 }
01738 
01739 static void dyn_enter(void) {
01740         gen_releasereg(DREG(ESP));
01741         gen_releasereg(DREG(EBP));
01742         Bitu bytes=decode_fetchw();
01743         Bitu level=decode_fetchb();
01744         gen_call_function((void *)&CPU_ENTER,"%Id%Id%Id",decode.big_op,bytes,level);
01745 }
01746 
01747 static void dyn_leave(void) {
01748         gen_protectflags();
01749         gen_dop_word_var(DOP_MOV,true,DREG(TMPW),&cpu.stack.mask);
01750         gen_sop_word(SOP_NOT,true,DREG(TMPW));
01751         gen_dop_word(DOP_AND,true,DREG(ESP),DREG(TMPW));
01752         gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(EBP));
01753         gen_dop_word_var(DOP_AND,true,DREG(TMPW),&cpu.stack.mask);
01754         gen_dop_word(DOP_OR,true,DREG(ESP),DREG(TMPW));
01755         dyn_pop(DREG(EBP),false);
01756         gen_releasereg(DREG(TMPW));
01757 }
01758 
01759 static void dyn_segprefix(SegNames seg) {
01760 //      if (GCC_UNLIKELY((Bitu)(decode.segprefix))) IllegalOption("dyn_segprefix");
01761         decode.segprefix=&DynRegs[G_ES+seg];
01762 }
01763 
01764 static void dyn_closeblock(void) {
01765         //Shouldn't create empty block normally but let's do it like this
01766         
01767         gen_protectflags();
01768         dyn_fill_blocks();
01769         cache_closeblock();
01770 }
01771 
01772 static void dyn_exit_link(Bits eip_change) {
01773         gen_protectflags();
01774         gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),(decode.code-decode.code_start)+eip_change);
01775         dyn_reduce_cycles();
01776         dyn_save_critical_regs();
01777         gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start));
01778         dyn_closeblock();
01779 }
01780 
01781 static void dyn_branched_exit(BranchTypes btype,Bit32s eip_add) {
01782         Bitu eip_base=decode.code-decode.code_start;
01783         gen_needflags();
01784         gen_protectflags();
01785         dyn_save_noncritical_regs();
01786         gen_releasereg(DREG(FLAGS));
01787         gen_releasereg(DREG(EIP));
01788 
01789         gen_preloadreg(DREG(CYCLES));
01790         gen_preloadreg(DREG(EIP));
01791         DynReg save_cycles,save_eip;
01792         dyn_saveregister(DREG(CYCLES),&save_cycles);
01793         dyn_saveregister(DREG(EIP),&save_eip);
01794         Bit8u * data=gen_create_branch(btype);
01795 
01796         /* Branch not taken */
01797         dyn_reduce_cycles();
01798         gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),eip_base);
01799         gen_releasereg(DREG(CYCLES));
01800         gen_releasereg(DREG(EIP));
01801         gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start));
01802         gen_fill_branch(data);
01803 
01804         /* Branch taken */
01805         dyn_restoreregister(&save_cycles,DREG(CYCLES));
01806         dyn_restoreregister(&save_eip,DREG(EIP));
01807         dyn_reduce_cycles();
01808         gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),eip_base+eip_add);
01809         gen_releasereg(DREG(CYCLES));
01810         gen_releasereg(DREG(EIP));
01811         gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlock,cache.start));
01812         dyn_closeblock();
01813 }
01814 
01815 enum LoopTypes {
01816         LOOP_NONE,LOOP_NE,LOOP_E,LOOP_JCXZ
01817 };
01818 
01819 static void dyn_loop(LoopTypes type) {
01820         dyn_reduce_cycles();
01821         Bits eip_add=(Bit8s)decode_fetchb();
01822         Bitu eip_base=decode.code-decode.code_start;
01823         Bit8u * branch1=0;Bit8u * branch2=0;
01824         dyn_save_critical_regs();
01825         switch (type) {
01826                 case LOOP_E:
01827                         gen_needflags();
01828                         branch1=gen_create_branch(BR_NZ);
01829                         break;
01830                 case LOOP_NE:
01831                         gen_needflags();
01832                         branch1=gen_create_branch(BR_Z);
01833                         break;
01834                 default:
01835                         break;
01836         }
01837         gen_protectflags();
01838         switch (type) {
01839                 case LOOP_E:
01840                 case LOOP_NE:
01841                 case LOOP_NONE:
01842                         gen_sop_word(SOP_DEC,decode.big_addr,DREG(ECX));
01843                         gen_releasereg(DREG(ECX));
01844                         branch2=gen_create_branch(BR_Z);
01845                         break;
01846                 case LOOP_JCXZ:
01847                         gen_dop_word(DOP_OR,decode.big_addr,DREG(ECX),DREG(ECX));
01848                         gen_releasereg(DREG(ECX));
01849                         branch2=gen_create_branch(BR_NZ);
01850                         break;
01851                 default:
01852                         break;
01853         }
01854         gen_lea(DREG(EIP),DREG(EIP),0,0,eip_base+eip_add);
01855         gen_releasereg(DREG(EIP));
01856         gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start));
01857         if (branch1) {
01858                 gen_fill_branch(branch1);
01859                 gen_sop_word(SOP_DEC,decode.big_addr,DREG(ECX));
01860                 gen_releasereg(DREG(ECX));
01861         }
01862         /* Branch taken */
01863         gen_fill_branch(branch2);
01864         gen_lea(DREG(EIP),DREG(EIP),0,0,eip_base);
01865         gen_releasereg(DREG(EIP));
01866         gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlock,cache.start));
01867         dyn_closeblock();
01868 }
01869 
01870 static void dyn_ret_near(Bitu bytes) {
01871         gen_protectflags();
01872         dyn_reduce_cycles();
01873         dyn_pop(DREG(EIP));
01874         if (bytes) gen_dop_word_imm(DOP_ADD,true,DREG(ESP),bytes);
01875         dyn_save_critical_regs();
01876         gen_return(BR_Normal);
01877         dyn_closeblock();
01878 }
01879 
01880 static void dyn_call_near_imm(void) {
01881         Bits imm;
01882         if (decode.big_op) imm=(Bit32s)decode_fetchd();
01883         else imm=(Bit16s)decode_fetchw();
01884         dyn_set_eip_end(DREG(TMPW));
01885         dyn_push(DREG(TMPW));
01886         gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(TMPW),imm);
01887         if (cpu.code.big) gen_dop_word(DOP_MOV,true,DREG(EIP),DREG(TMPW));
01888         else gen_extend_word(false,DREG(EIP),DREG(TMPW));
01889         dyn_reduce_cycles();
01890         dyn_save_critical_regs();
01891         gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start));
01892         dyn_closeblock();
01893 }
01894 
01895 static void dyn_ret_far(Bitu bytes) {
01896         gen_protectflags();
01897         dyn_reduce_cycles();
01898         dyn_set_eip_last_end(DREG(TMPW));
01899         dyn_flags_gen_to_host();
01900         dyn_save_critical_regs();
01901         gen_call_function((void*)&CPU_RET,"%Id%Id%Drd",decode.big_op,bytes,DREG(TMPW));
01902         gen_return_fast(BR_Normal);
01903         dyn_closeblock();
01904 }
01905 
01906 static void dyn_call_far_imm(void) {
01907         Bitu sel,off;
01908         off=decode.big_op ? decode_fetchd() : decode_fetchw();
01909         sel=decode_fetchw();
01910         dyn_reduce_cycles();
01911         dyn_set_eip_last_end(DREG(TMPW));
01912         dyn_flags_gen_to_host();
01913         dyn_save_critical_regs();
01914         gen_call_function((void*)&CPU_CALL,"%Id%Id%Id%Drd",decode.big_op,sel,off,DREG(TMPW));
01915         gen_return_fast(BR_Normal);
01916         dyn_closeblock();
01917 }
01918 
01919 static void dyn_jmp_far_imm(void) {
01920         Bitu sel,off;
01921         gen_protectflags();
01922         off=decode.big_op ? decode_fetchd() : decode_fetchw();
01923         sel=decode_fetchw();
01924         dyn_reduce_cycles();
01925         dyn_set_eip_last_end(DREG(TMPW));
01926         dyn_flags_gen_to_host();
01927         dyn_save_critical_regs();
01928         gen_call_function((void*)&CPU_JMP,"%Id%Id%Id%Drd",decode.big_op,sel,off,DREG(TMPW));
01929         gen_return_fast(BR_Normal);
01930         dyn_closeblock();
01931 }
01932 
01933 static void dyn_iret(void) {
01934         gen_protectflags();
01935         dyn_flags_gen_to_host();
01936         dyn_reduce_cycles();
01937         dyn_set_eip_last_end(DREG(TMPW));
01938         dyn_save_critical_regs();
01939         gen_call_function((void*)&CPU_IRET,"%Id%Drd",decode.big_op,DREG(TMPW));
01940         gen_return_fast(BR_Iret);
01941         dyn_closeblock();
01942 }
01943 
01944 static void dyn_add_iocheck(Bitu access_size) {
01945         gen_call_function((void *)&CPU_IO_Exception,"%Dw%Id",DREG(EDX),access_size);
01946         dyn_check_bool_exception_al();
01947 }
01948 
01949 static void dyn_add_iocheck_var(Bit8u accessed_port,Bitu access_size) {
01950         gen_call_function((void *)&CPU_IO_Exception,"%Id%Id",accessed_port,access_size);
01951         dyn_check_bool_exception_al();
01952 }
01953 
01954 #ifdef X86_DYNFPU_DH_ENABLED
01955 #include "dyn_fpu_dh.h"
01956 #define dh_fpu_startup() {              \
01957         fpu_used=true;                          \
01958         gen_protectflags();                     \
01959         gen_load_host(&dyn_dh_fpu.state_used,DREG(TMPB),4);     \
01960         gen_dop_word_imm(DOP_CMP,true,DREG(TMPB),0);            \
01961         gen_releasereg(DREG(TMPB));                                                     \
01962         save_info[used_save_info].branch_pos=gen_create_branch_long(BR_Z);              \
01963         dyn_savestate(&save_info[used_save_info].state);        \
01964         save_info[used_save_info].return_pos=cache.pos;         \
01965         save_info[used_save_info].type=fpu_restore;                     \
01966         used_save_info++;                                                                       \
01967 }
01968 #endif
01969 #include "dyn_fpu.h"
01970 
01971 #ifdef X86_DYNREC_MMX_ENABLED
01972 #include "mmx_gen.h"
01973 #define dyn_mmx_check() if ((dyn_dh_fpu.dh_fpu_enabled) && (!fpu_used)) {dh_fpu_startup();}
01974 #endif
01975 
01976 static CacheBlock * CreateCacheBlock(CodePageHandler * codepage,PhysPt start,Bitu max_opcodes) {
01977         Bits i;
01978 /* Init a load of variables */
01979         decode.code_start=start;
01980         decode.code=start;
01981         decode.page.code=codepage;
01982         decode.page.index=start&4095;
01983         decode.page.wmap=codepage->write_map;
01984         decode.page.invmap=codepage->invalidation_map;
01985         decode.page.first=start >> 12;
01986         decode.active_block=decode.block=cache_openblock();
01987         decode.block->page.start=decode.page.index;
01988         codepage->AddCacheBlock(decode.block);
01989 
01990         gen_save_host_direct(&cache.block.running,(uintptr_t)decode.block);
01991         for (i=0;i<G_MAX;i++) {
01992                 DynRegs[i].flags&=~(DYNFLG_ACTIVE|DYNFLG_CHANGED);
01993                 DynRegs[i].genreg=0;
01994         }
01995         gen_reinit();
01996         /* Start with the cycles check */
01997         gen_protectflags();
01998         gen_dop_word_imm(DOP_CMP,true,DREG(CYCLES),0);
01999         save_info[used_save_info].branch_pos=gen_create_branch_long(BR_LE);
02000         save_info[used_save_info].type=cycle_check;
02001         used_save_info++;
02002         gen_releasereg(DREG(CYCLES));
02003         decode.cycles=0;
02004 #ifdef X86_DYNFPU_DH_ENABLED
02005         bool fpu_used=false;
02006 #endif
02007 
02008         while (max_opcodes--) {
02009 /* Init prefixes */
02010                 decode.big_addr=cpu.code.big;
02011                 decode.big_op=cpu.code.big;
02012                 decode.segprefix=0;
02013                 decode.rep=REP_NONE;
02014                 decode.cycles++;
02015                 decode.op_start=decode.code;
02016 restart_prefix:
02017                 Bitu opcode;
02018                 if (!decode.page.invmap) opcode=decode_fetchb();
02019                 else {
02020                         if (decode.page.index<4096) {
02021                                 if (GCC_UNLIKELY(decode.page.invmap[decode.page.index]>=4)) goto illegalopcode;
02022                                 opcode=decode_fetchb();
02023                         } else {
02024                                 opcode=decode_fetchb();
02025                                 if (GCC_UNLIKELY(decode.page.invmap && 
02026                                         (decode.page.invmap[decode.page.index-1]>=4))) goto illegalopcode;
02027                         }
02028                 }
02029                 switch (opcode) {
02030 
02031                 case 0x00:dyn_dop_ebgb(DOP_ADD);break;
02032                 case 0x01:dyn_dop_evgv(DOP_ADD);break;
02033                 case 0x02:dyn_dop_gbeb(DOP_ADD);break;
02034                 case 0x03:dyn_dop_gvev(DOP_ADD);break;
02035                 case 0x04:gen_discardflags();gen_dop_byte_imm(DOP_ADD,DREG(EAX),0,decode_fetchb());break;
02036                 case 0x05:gen_discardflags();dyn_dop_word_imm(DOP_ADD,decode.big_op,DREG(EAX));break;
02037                 case 0x06:dyn_push_seg(es);break;
02038                 case 0x07:dyn_pop_seg(es);break;
02039 
02040                 case 0x08:dyn_dop_ebgb(DOP_OR);break;
02041                 case 0x09:dyn_dop_evgv(DOP_OR);break;
02042                 case 0x0a:dyn_dop_gbeb(DOP_OR);break;
02043                 case 0x0b:dyn_dop_gvev(DOP_OR);break;
02044                 case 0x0c:gen_discardflags();gen_dop_byte_imm(DOP_OR,DREG(EAX),0,decode_fetchb());break;
02045                 case 0x0d:gen_discardflags();gen_dop_word_imm(DOP_OR,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() :  decode_fetchw());break;
02046                 case 0x0e:dyn_push_seg(cs);break;
02047                 case 0x0f:
02048                 {
02049                         Bitu dual_code=decode_fetchb();
02050 
02051                         switch (dual_code) {
02052                         /* Short conditional jumps */
02053                         case 0x80:case 0x81:case 0x82:case 0x83:case 0x84:case 0x85:case 0x86:case 0x87:        
02054                         case 0x88:case 0x89:case 0x8a:case 0x8b:case 0x8c:case 0x8d:case 0x8e:case 0x8f:        
02055                                 dyn_branched_exit((BranchTypes)(dual_code&0xf),
02056                                         decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw());     
02057                                 goto finish_block;
02058                         /* PUSH/POP FS */
02059                         case 0xa0:dyn_push_seg(fs);break;
02060                         case 0xa1:dyn_pop_seg(fs);break;
02061                         /* SHLD Imm/cl*/
02062                         case 0xa4:dyn_dshift_ev_gv(true,true);break;
02063                         case 0xa5:dyn_dshift_ev_gv(true,false);break;
02064                         /* PUSH/POP GS */
02065                         case 0xa8:dyn_push_seg(gs);break;
02066                         case 0xa9:dyn_pop_seg(gs);break;
02067                         /* SHRD Imm/cl*/
02068                         case 0xac:dyn_dshift_ev_gv(false,true);break;
02069                         case 0xad:dyn_dshift_ev_gv(false,false);break;          
02070                         /* Imul Ev,Gv */
02071                         case 0xaf:dyn_imul_gvev(0);break;
02072                         /* CMPXCHG */
02073                         case 0xb1:dyn_cmpxchg_evgv();break;
02074                         /* LFS,LGS */
02075                         case 0xb4:
02076                                 dyn_get_modrm();
02077                                 if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode;
02078                                 dyn_load_seg_off_ea(fs);
02079                                 break;
02080                         case 0xb5:
02081                                 dyn_get_modrm();
02082                                 if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode;
02083                                 dyn_load_seg_off_ea(gs);
02084                                 break;
02085                         /* MOVZX Gv,Eb/Ew */
02086                         case 0xb6:dyn_mov_ev_gb(false);break;
02087                         case 0xb7:dyn_mov_ev_gw(false);break;
02088                         /* MOVSX Gv,Eb/Ew */
02089                         case 0xbe:dyn_mov_ev_gb(true);break;
02090                         case 0xbf:dyn_mov_ev_gw(true);break;
02091 
02092 #if defined(X86_DYNREC_MMX_ENABLED) && defined(X86_DYNFPU_DH_ENABLED)
02093                         
02094                         /* OP mm, mm/m64 */
02095                         /* pack/unpacks, compares */
02096                         case 0x60:case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:
02097                         case 0x66:case 0x67:case 0x68:case 0x69:case 0x6a:case 0x6b:
02098                         case 0x74:case 0x75:case 0x76:
02099                         /* mm-directed shifts, add/sub, bitwise, multiplies */
02100                         case 0xd1:case 0xd2:case 0xd3:case 0xd4:case 0xd5:case 0xd8:
02101                         case 0xd9:case 0xdb:case 0xdc:case 0xdd:case 0xdf:case 0xe1:
02102                         case 0xe2:case 0xe5:case 0xe8:case 0xe9:case 0xeb:case 0xec:
02103                         case 0xed:case 0xef:case 0xf1:case 0xf2:case 0xf3:case 0xf5:
02104                         case 0xf8:case 0xf9:case 0xfa:case 0xfc:case 0xfd:case 0xfe:
02105                                 dyn_mmx_check(); dyn_mmx_op(dual_code); break;
02106 
02107                         /* SHIFT mm, imm8*/
02108                         case 0x71:case 0x72:case 0x73:
02109                                 dyn_mmx_check(); dyn_mmx_shift_imm8(dual_code); break;
02110 
02111                         /* MOVD mm, r/m32 */
02112                         case 0x6e:dyn_mmx_check(); dyn_mmx_movd_pqed(); break;
02113                         /* MOVQ mm, mm/m64 */
02114                         case 0x6f:dyn_mmx_check(); dyn_mmx_movq_pqqq(); break;
02115                         /* MOVD r/m32, mm */
02116                         case 0x7e:dyn_mmx_check(); dyn_mmx_movd_edpq(); break;
02117                         /* MOVQ mm/m64, mm */
02118                         case 0x7f:dyn_mmx_check(); dyn_mmx_movq_qqpq(); break;
02119                         /* EMMS */
02120                         case 0x77:dyn_mmx_check(); dyn_mmx_emms(); break;
02121 #endif
02122 
02123                         default:
02124 
02125 #if DYN_LOG
02126                                 LOG_MSG("Unhandled dual opcode 0F%02X", dual_code);
02127 #endif
02128                                 goto illegalopcode;
02129                         }
02130                 }break;
02131 
02132                 case 0x10:dyn_dop_ebgb(DOP_ADC);break;
02133                 case 0x11:dyn_dop_evgv(DOP_ADC);break;
02134                 case 0x12:dyn_dop_gbeb(DOP_ADC);break;
02135                 case 0x13:dyn_dop_gvev(DOP_ADC);break;
02136                 case 0x14:gen_needcarry();gen_dop_byte_imm(DOP_ADC,DREG(EAX),0,decode_fetchb());break;
02137                 case 0x15:gen_needcarry();gen_dop_word_imm(DOP_ADC,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() :  decode_fetchw());break;
02138                 case 0x16:dyn_push_seg(ss);break;
02139                 case 0x17:dyn_pop_seg(ss);break;
02140 
02141                 case 0x18:dyn_dop_ebgb(DOP_SBB);break;
02142                 case 0x19:dyn_dop_evgv(DOP_SBB);break;
02143                 case 0x1a:dyn_dop_gbeb(DOP_SBB);break;
02144                 case 0x1b:dyn_dop_gvev(DOP_SBB);break;
02145                 case 0x1c:gen_needcarry();gen_dop_byte_imm(DOP_SBB,DREG(EAX),0,decode_fetchb());break;
02146                 case 0x1d:gen_needcarry();gen_dop_word_imm(DOP_SBB,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() :  decode_fetchw());break;
02147                 case 0x1e:dyn_push_seg(ds);break;
02148                 case 0x1f:dyn_pop_seg(ds);break;
02149                 case 0x20:dyn_dop_ebgb(DOP_AND);break;
02150                 case 0x21:dyn_dop_evgv(DOP_AND);break;
02151                 case 0x22:dyn_dop_gbeb(DOP_AND);break;
02152                 case 0x23:dyn_dop_gvev(DOP_AND);break;
02153                 case 0x24:gen_discardflags();gen_dop_byte_imm(DOP_AND,DREG(EAX),0,decode_fetchb());break;
02154                 case 0x25:gen_discardflags();dyn_dop_word_imm(DOP_AND,decode.big_op,DREG(EAX));break;
02155                 case 0x26:dyn_segprefix(es);goto restart_prefix;
02156 
02157                 case 0x28:dyn_dop_ebgb(DOP_SUB);break;
02158                 case 0x29:dyn_dop_evgv(DOP_SUB);break;
02159                 case 0x2a:dyn_dop_gbeb(DOP_SUB);break;
02160                 case 0x2b:dyn_dop_gvev(DOP_SUB);break;
02161                 case 0x2c:gen_discardflags();gen_dop_byte_imm(DOP_SUB,DREG(EAX),0,decode_fetchb());break;
02162                 case 0x2d:gen_discardflags();gen_dop_word_imm(DOP_SUB,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() :  decode_fetchw());break;
02163                 case 0x2e:dyn_segprefix(cs);goto restart_prefix;
02164 
02165                 case 0x30:dyn_dop_ebgb(DOP_XOR);break;
02166                 case 0x31:dyn_dop_evgv(DOP_XOR);break;
02167                 case 0x32:dyn_dop_gbeb(DOP_XOR);break;
02168                 case 0x33:dyn_dop_gvev(DOP_XOR);break;
02169                 case 0x34:gen_discardflags();gen_dop_byte_imm(DOP_XOR,DREG(EAX),0,decode_fetchb());break;
02170                 case 0x35:gen_discardflags();gen_dop_word_imm(DOP_XOR,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() :  decode_fetchw());break;
02171                 case 0x36:dyn_segprefix(ss);goto restart_prefix;
02172 
02173                 case 0x38:dyn_dop_ebgb(DOP_CMP);break;
02174                 case 0x39:dyn_dop_evgv(DOP_CMP);break;
02175                 case 0x3a:dyn_dop_gbeb(DOP_CMP);break;
02176                 case 0x3b:dyn_dop_gvev(DOP_CMP);break;
02177                 case 0x3c:gen_discardflags();gen_dop_byte_imm(DOP_CMP,DREG(EAX),0,decode_fetchb());break;
02178                 case 0x3d:gen_discardflags();gen_dop_word_imm(DOP_CMP,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() :  decode_fetchw());break;
02179                 case 0x3e:dyn_segprefix(ds);goto restart_prefix;
02180 
02181                 /* INC/DEC general register */
02182                 case 0x40:case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:case 0x47:        
02183                         gen_needcarry();gen_sop_word(SOP_INC,decode.big_op,&DynRegs[opcode&7]);
02184                         break;
02185                 case 0x48:case 0x49:case 0x4a:case 0x4b:case 0x4c:case 0x4d:case 0x4e:case 0x4f:        
02186                         gen_needcarry();gen_sop_word(SOP_DEC,decode.big_op,&DynRegs[opcode&7]);
02187                         break;
02188                 /* PUSH/POP General register */
02189                 case 0x50:case 0x51:case 0x52:case 0x53:case 0x55:case 0x56:case 0x57:  
02190                         dyn_push(&DynRegs[opcode&7]);
02191                         break;
02192                 case 0x54:              /* PUSH SP is special */
02193                         gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(ESP));
02194                         dyn_push(DREG(TMPW));
02195                         gen_releasereg(DREG(TMPW));
02196                         break;
02197                 case 0x58:case 0x59:case 0x5a:case 0x5b:case 0x5c:case 0x5d:case 0x5e:case 0x5f:        
02198                         dyn_pop(&DynRegs[opcode&7]);
02199                         break;
02200                 case 0x60:              /* PUSHA */
02201                         gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(ESP));
02202                         for (i=G_EAX;i<=G_EDI;i++) {
02203                                 dyn_push_unchecked((i!=G_ESP) ? &DynRegs[i] : DREG(TMPW));
02204                         }
02205                         gen_releasereg(DREG(TMPW));
02206                         break;
02207                 case 0x61:              /* POPA */
02208                         for (i=G_EDI;i>=G_EAX;i--) {
02209                                 dyn_pop((i!=G_ESP) ? &DynRegs[i] : DREG(TMPW),false);
02210                         }
02211                         gen_releasereg(DREG(TMPW));
02212                         break;
02213                 //segprefix FS,GS
02214                 case 0x64:dyn_segprefix(fs);goto restart_prefix;
02215                 case 0x65:dyn_segprefix(gs);goto restart_prefix;
02216                 //Push immediates
02217                 //Operand size          
02218                 case 0x66:decode.big_op=!cpu.code.big;goto restart_prefix;
02219                 //Address size          
02220                 case 0x67:decode.big_addr=!cpu.code.big;goto restart_prefix;
02221                 case 0x68:              /* PUSH Iv */
02222                         gen_dop_word_imm(DOP_MOV,decode.big_op,DREG(TMPW),decode.big_op ? decode_fetchd() : decode_fetchw());
02223                         dyn_push(DREG(TMPW));
02224                         gen_releasereg(DREG(TMPW));
02225                         break;
02226                 /* Imul Ivx */
02227                 case 0x69:dyn_imul_gvev(decode.big_op ? 4 : 2);break;
02228                 case 0x6a:              /* PUSH Ibx */
02229                         gen_dop_word_imm(DOP_MOV,true,DREG(TMPW),(Bit8s)decode_fetchb());
02230                         dyn_push(DREG(TMPW));
02231                         gen_releasereg(DREG(TMPW));
02232                         break;
02233                 /* Imul Ibx */
02234                 case 0x6b:dyn_imul_gvev(1);break;
02235                 /* Short conditional jumps */
02236                 case 0x70:case 0x71:case 0x72:case 0x73:case 0x74:case 0x75:case 0x76:case 0x77:        
02237                 case 0x78:case 0x79:case 0x7a:case 0x7b:case 0x7c:case 0x7d:case 0x7e:case 0x7f:        
02238                         dyn_branched_exit((BranchTypes)(opcode&0xf),(Bit8s)decode_fetchb());    
02239                         goto finish_block;
02240                 /* Group 1 */
02241                 case 0x80:dyn_grp1_eb_ib();break;
02242                 case 0x81:dyn_grp1_ev_ivx(false);break;
02243                 case 0x82:dyn_grp1_eb_ib();break;
02244                 case 0x83:dyn_grp1_ev_ivx(true);break;
02245                 /* TEST Gb,Eb Gv,Ev */
02246                 case 0x84:dyn_dop_gbeb(DOP_TEST);break;
02247                 case 0x85:dyn_dop_gvev(DOP_TEST);break;
02248                 /* XCHG Eb,Gb Ev,Gv */
02249                 case 0x86:dyn_dop_ebgb(DOP_XCHG);break;
02250                 case 0x87:dyn_dop_evgv(DOP_XCHG);break;
02251                 /* MOV e,g and g,e */
02252                 case 0x88:dyn_mov_ebgb();break;
02253                 case 0x89:dyn_mov_evgv();break;
02254                 case 0x8a:dyn_mov_gbeb();break;
02255                 case 0x8b:dyn_mov_gvev();break;
02256                 /* MOV ev,seg */
02257                 case 0x8c:dyn_mov_ev_seg();break;
02258                 /* LEA Gv */
02259                 case 0x8d:
02260                         dyn_get_modrm();
02261                         if (decode.big_op) {
02262                                 dyn_fill_ea(false,&DynRegs[decode.modrm.reg]);
02263                         } else {
02264                                 dyn_fill_ea(false);
02265                                 gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.reg],DREG(EA));
02266                                 gen_releasereg(DREG(EA));
02267                         }
02268                         break;
02269                 /* Mov seg,ev */
02270                 case 0x8e:dyn_mov_seg_ev();break;
02271                 /* POP Ev */
02272                 case 0x8f:dyn_pop_ev();break;
02273                 case 0x90:      //NOP
02274                 case 0x9b:      //WAIT/FWAIT
02275                         break;
02276                 //XCHG ax,reg
02277                 case 0x91:case 0x92:case 0x93:case 0x94:case 0x95:case 0x96:case 0x97:  
02278                         gen_dop_word(DOP_XCHG,decode.big_op,DREG(EAX),&DynRegs[opcode&07]);
02279                         break;
02280                 /* CBW/CWDE */
02281                 case 0x98:
02282                         gen_cbw(decode.big_op,DREG(EAX));
02283                         break;
02284                 /* CWD/CDQ */
02285                 case 0x99:
02286                         gen_cwd(decode.big_op,DREG(EAX),DREG(EDX));
02287                         break;
02288                 /* CALL FAR Ip */
02289                 case 0x9a:dyn_call_far_imm();goto finish_block;
02290                 case 0x9c:              //PUSHF
02291                         gen_protectflags();
02292                         gen_releasereg(DREG(ESP));
02293                         dyn_flags_gen_to_host();
02294                         gen_call_function((void *)&CPU_PUSHF,"%Rd%Id",DREG(TMPB),decode.big_op);
02295                         dyn_check_bool_exception(DREG(TMPB));
02296                         gen_releasereg(DREG(TMPB));
02297                         break;
02298                 case 0x9d:              //POPF
02299                         gen_releasereg(DREG(ESP));
02300                         gen_releasereg(DREG(FLAGS));
02301                         gen_call_function((void *)&CPU_POPF,"%Rd%Id",DREG(TMPB),decode.big_op);
02302                         dyn_check_bool_exception(DREG(TMPB));
02303                         dyn_flags_host_to_gen();
02304                         gen_releasereg(DREG(TMPB));
02305                         dyn_check_irqrequest();
02306                         break;
02307                 /* MOV AL,direct addresses */
02308                 case 0xa0:
02309                         gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0,
02310                                 decode.big_addr ? decode_fetchd() : decode_fetchw());
02311                         dyn_read_byte_release(DREG(EA),DREG(EAX),false);
02312                         break;
02313                 /* MOV AX,direct addresses */
02314                 case 0xa1:
02315                         gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0,
02316                                 decode.big_addr ? decode_fetchd() : decode_fetchw());
02317                         dyn_read_word_release(DREG(EA),DREG(EAX),decode.big_op);
02318                         break;
02319                 /* MOV direct address,AL */
02320                 case 0xa2:
02321                         if (decode.big_addr) {
02322                                 Bitu val;
02323                                 if (decode_fetchd_imm(val)) {
02324                                         gen_lea_imm_mem(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),(void*)val);
02325                                 } else {
02326                                         gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0,(Bits)val);
02327                                 }
02328                                 dyn_write_byte_release(DREG(EA),DREG(EAX),false);
02329                         } else {
02330                                 gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0,decode_fetchw());
02331                                 dyn_write_byte_release(DREG(EA),DREG(EAX),false);
02332                         }
02333                         break;
02334                 /* MOV direct addresses,AX */
02335                 case 0xa3:
02336                         gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0,
02337                                 decode.big_addr ? decode_fetchd() : decode_fetchw());
02338                         dyn_write_word_release(DREG(EA),DREG(EAX),decode.big_op);
02339                         break;
02340                 /* MOVSB/W/D*/
02341                 case 0xa4:dyn_string(STR_MOVSB);break;
02342                 case 0xa5:dyn_string(decode.big_op ? STR_MOVSD : STR_MOVSW);break;
02343                 /* TEST AL,AX Imm */
02344                 case 0xa8:gen_discardflags();gen_dop_byte_imm(DOP_TEST,DREG(EAX),0,decode_fetchb());break;
02345                 case 0xa9:gen_discardflags();gen_dop_word_imm(DOP_TEST,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() :  decode_fetchw());break;
02346                 /* STOSB/W/D*/
02347                 case 0xaa:dyn_string(STR_STOSB);break;
02348                 case 0xab:dyn_string(decode.big_op ? STR_STOSD : STR_STOSW);break;
02349                 /* LODSB/W/D*/
02350                 case 0xac:dyn_string(STR_LODSB);break;
02351                 case 0xad:dyn_string(decode.big_op ? STR_LODSD : STR_LODSW);break;
02352                 //Mov Byte reg,Imm byte
02353                 case 0xb0:case 0xb1:case 0xb2:case 0xb3:case 0xb4:case 0xb5:case 0xb6:case 0xb7:        
02354                         gen_dop_byte_imm(DOP_MOV,&DynRegs[opcode&3],opcode&4,decode_fetchb());
02355                         break;
02356                 //Mov word reg imm byte,word,
02357                 case 0xb8:case 0xb9:case 0xba:case 0xbb:case 0xbc:case 0xbd:case 0xbe:case 0xbf:        
02358                         if (decode.big_op) {
02359                                 dyn_dop_word_imm(DOP_MOV,decode.big_op,&DynRegs[opcode&7]);break;
02360                         } else {
02361                                 gen_dop_word_imm(DOP_MOV,decode.big_op,&DynRegs[opcode&7],decode_fetchw());break;
02362                         }
02363                         break;
02364                 //GRP2 Eb/Ev,Ib
02365                 case 0xc0:dyn_grp2_eb(grp2_imm);break;
02366                 case 0xc1:dyn_grp2_ev(grp2_imm);break;
02367                 //RET near Iw / Ret
02368                 case 0xc2:dyn_ret_near(decode_fetchw());goto finish_block;
02369                 case 0xc3:dyn_ret_near(0);goto finish_block;
02370                 //LES
02371                 case 0xc4:
02372                         dyn_get_modrm();
02373                         if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode;
02374                         dyn_load_seg_off_ea(es);
02375                         break;
02376                 //LDS
02377                 case 0xc5:
02378                         dyn_get_modrm();
02379                         if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode;
02380                         dyn_load_seg_off_ea(ds);
02381                         break;
02382                 // MOV Eb/Ev,Ib/Iv
02383                 case 0xc6:dyn_mov_ebib();break;
02384                 case 0xc7:dyn_mov_eviv();break;
02385                 //ENTER and LEAVE
02386                 case 0xc8:dyn_enter();break;
02387                 case 0xc9:dyn_leave();break;
02388                 //RET far Iw / Ret
02389                 case 0xca:dyn_ret_far(decode_fetchw());goto finish_block;
02390                 case 0xcb:dyn_ret_far(0);goto finish_block;
02391                 /* IRET */
02392                 case 0xcf:dyn_iret();goto finish_block;
02393 
02394                 //GRP2 Eb/Ev,1
02395                 case 0xd0:dyn_grp2_eb(grp2_1);break;
02396                 case 0xd1:dyn_grp2_ev(grp2_1);break;
02397                 //GRP2 Eb/Ev,CL
02398                 case 0xd2:dyn_grp2_eb(grp2_cl);break;
02399                 case 0xd3:dyn_grp2_ev(grp2_cl);break;
02400                 //FPU
02401 #ifdef CPU_FPU
02402                 case 0xd8:
02403 #ifdef X86_DYNFPU_DH_ENABLED
02404                         if (dyn_dh_fpu.dh_fpu_enabled) {
02405                                 if (fpu_used) dh_fpu_esc0();
02406                                 else {
02407                                         dh_fpu_startup();
02408                                         dh_fpu_esc0();
02409                                 }
02410                         } else
02411 #endif
02412                         dyn_fpu_esc0();
02413                         break;
02414                 case 0xd9:
02415 #ifdef X86_DYNFPU_DH_ENABLED
02416                         if (dyn_dh_fpu.dh_fpu_enabled) {
02417                                 if (fpu_used) dh_fpu_esc1();
02418                                 else {
02419                                         dh_fpu_startup();
02420                                         dh_fpu_esc1();
02421                                 }
02422                         } else
02423 #endif
02424                         dyn_fpu_esc1();
02425                         break;
02426                 case 0xda:
02427 #ifdef X86_DYNFPU_DH_ENABLED
02428                         if (dyn_dh_fpu.dh_fpu_enabled) {
02429                                 if (fpu_used) dh_fpu_esc2();
02430                                 else {
02431                                         dh_fpu_startup();
02432                                         dh_fpu_esc2();
02433                                 }
02434                         } else
02435 #endif
02436                         dyn_fpu_esc2();
02437                         break;
02438                 case 0xdb:
02439 #ifdef X86_DYNFPU_DH_ENABLED
02440                         if (dyn_dh_fpu.dh_fpu_enabled) {
02441                                 if (fpu_used) dh_fpu_esc3();
02442                                 else {
02443                                         dh_fpu_startup();
02444                                         dh_fpu_esc3();
02445                                 }
02446                         } else
02447 #endif
02448                         dyn_fpu_esc3();
02449                         break;
02450                 case 0xdc:
02451 #ifdef X86_DYNFPU_DH_ENABLED
02452                         if (dyn_dh_fpu.dh_fpu_enabled) {
02453                                 if (fpu_used) dh_fpu_esc4();
02454                                 else {
02455                                         dh_fpu_startup();
02456                                         dh_fpu_esc4();
02457                                 }
02458                         } else
02459 #endif
02460                         dyn_fpu_esc4();
02461                         break;
02462                 case 0xdd:
02463 #ifdef X86_DYNFPU_DH_ENABLED
02464                         if (dyn_dh_fpu.dh_fpu_enabled) {
02465                                 if (fpu_used) dh_fpu_esc5();
02466                                 else {
02467                                         dh_fpu_startup();
02468                                         dh_fpu_esc5();
02469                                 }
02470                         } else
02471 #endif
02472                         dyn_fpu_esc5();
02473                         break;
02474                 case 0xde:
02475 #ifdef X86_DYNFPU_DH_ENABLED
02476                         if (dyn_dh_fpu.dh_fpu_enabled) {
02477                                 if (fpu_used) dh_fpu_esc6();
02478                                 else {
02479                                         dh_fpu_startup();
02480                                         dh_fpu_esc6();
02481                                 }
02482                         } else
02483 #endif
02484                         dyn_fpu_esc6();
02485                         break;
02486                 case 0xdf:
02487 #ifdef X86_DYNFPU_DH_ENABLED
02488                         if (dyn_dh_fpu.dh_fpu_enabled) {
02489                                 if (fpu_used) dh_fpu_esc7();
02490                                 else {
02491                                         dh_fpu_startup();
02492                                         dh_fpu_esc7();
02493                                 }
02494                         } else
02495 #endif
02496                         dyn_fpu_esc7();
02497                         break;
02498 #endif
02499                 //Loops 
02500                 case 0xe2:dyn_loop(LOOP_NONE);goto finish_block;
02501                 case 0xe3:dyn_loop(LOOP_JCXZ);goto finish_block;
02502                 //IN AL/AX,imm
02503                 case 0xe4: {
02504                         Bitu port=decode_fetchb();
02505                         dyn_add_iocheck_var(port,1);
02506                         gen_call_function((void*)&IO_ReadB,"%Id%Rl",port,DREG(EAX));
02507                         } break;
02508                 case 0xe5: {
02509                         Bitu port=decode_fetchb();
02510                         dyn_add_iocheck_var(port,decode.big_op?4:2);
02511                         if (decode.big_op) {
02512                 gen_call_function((void*)&IO_ReadD,"%Id%Rd",port,DREG(EAX));
02513                         } else {
02514                                 gen_call_function((void*)&IO_ReadW,"%Id%Rw",port,DREG(EAX));
02515                         }
02516                         } break;
02517                 //OUT imm,AL
02518                 case 0xe6: {
02519                         Bitu port=decode_fetchb();
02520                         dyn_add_iocheck_var(port,1);
02521                         gen_call_function((void*)&IO_WriteB,"%Id%Dl",port,DREG(EAX));
02522                         } break;
02523                 case 0xe7: {
02524                         Bitu port=decode_fetchb();
02525                         dyn_add_iocheck_var(port,decode.big_op?4:2);
02526                         if (decode.big_op) {
02527                 gen_call_function((void*)&IO_WriteD,"%Id%Dd",port,DREG(EAX));
02528                         } else {
02529                                 gen_call_function((void*)&IO_WriteW,"%Id%Dw",port,DREG(EAX));
02530                         }
02531                         } break;
02532                 case 0xe8:              /* CALL Ivx */
02533                         dyn_call_near_imm();
02534                         goto finish_block;
02535                 case 0xe9:              /* Jmp Ivx */
02536                         dyn_exit_link(decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw());
02537                         goto finish_block;
02538                 case 0xea:              /* JMP FAR Ip */
02539                         dyn_jmp_far_imm();
02540                         goto finish_block;
02541                         /* Jmp Ibx */
02542                 case 0xeb:dyn_exit_link((Bit8s)decode_fetchb());goto finish_block;
02543                 /* IN AL/AX,DX*/
02544                 case 0xec:
02545                         dyn_add_iocheck(1);
02546                         gen_call_function((void*)&IO_ReadB,"%Dw%Rl",DREG(EDX),DREG(EAX));
02547                         break;
02548                 case 0xed:
02549                         dyn_add_iocheck(decode.big_op?4:2);
02550                         if (decode.big_op) {
02551                 gen_call_function((void*)&IO_ReadD,"%Dw%Rd",DREG(EDX),DREG(EAX));
02552                         } else {
02553                                 gen_call_function((void*)&IO_ReadW,"%Dw%Rw",DREG(EDX),DREG(EAX));
02554                         }
02555                         break;
02556                 /* OUT DX,AL/AX */
02557                 case 0xee:
02558                         dyn_add_iocheck(1);
02559                         gen_call_function((void*)&IO_WriteB,"%Dw%Dl",DREG(EDX),DREG(EAX));
02560                         break;
02561                 case 0xef:
02562                         dyn_add_iocheck(decode.big_op?4:2);
02563                         if (decode.big_op) {
02564                 gen_call_function((void*)&IO_WriteD,"%Dw%Dd",DREG(EDX),DREG(EAX));
02565                         } else {
02566                                 gen_call_function((void*)&IO_WriteW,"%Dw%Dw",DREG(EDX),DREG(EAX));
02567                         }
02568                         break;
02569                 case 0xf0:              //LOCK
02570                         break;
02571                 case 0xf2:              //REPNE/NZ
02572                         decode.rep=REP_NZ;
02573                         goto restart_prefix;
02574                 case 0xf3:              //REPE/Z
02575                         decode.rep=REP_Z;
02576                         goto restart_prefix;
02577                 /* Change carry flag */
02578                 case 0xf5:              //CMC
02579                 case 0xf8:              //CLC
02580                 case 0xf9:              //STC
02581                         gen_needflags();
02582                         cache_addb(opcode);break;
02583                 /* GRP 3 Eb/EV */
02584                 case 0xf6:dyn_grp3_eb();break;
02585                 case 0xf7:dyn_grp3_ev();break;
02586                 /* Change interrupt flag */
02587                 case 0xfa:              //CLI
02588                         gen_releasereg(DREG(FLAGS));
02589                         gen_call_function((void *)&CPU_CLI,"%Rd",DREG(TMPB));
02590                         dyn_check_bool_exception(DREG(TMPB));
02591                         gen_releasereg(DREG(TMPB));
02592                         break;
02593                 case 0xfb:              //STI
02594                         gen_releasereg(DREG(FLAGS));
02595                         gen_call_function((void *)&CPU_STI,"%Rd",DREG(TMPB));
02596                         dyn_check_bool_exception(DREG(TMPB));
02597                         gen_releasereg(DREG(TMPB));
02598                         dyn_check_irqrequest();
02599                         if (max_opcodes<=0) max_opcodes=1;              //Allow 1 extra opcode
02600                         break;
02601                 case 0xfc:              //CLD
02602                         gen_protectflags();
02603                         gen_dop_word_imm(DOP_AND,true,DREG(FLAGS),~FLAG_DF);
02604                         gen_save_host_direct(&cpu.direction,1);
02605                         break;
02606                 case 0xfd:              //STD
02607                         gen_protectflags();
02608                         gen_dop_word_imm(DOP_OR,true,DREG(FLAGS),FLAG_DF);
02609                         gen_save_host_direct(&cpu.direction,-1);
02610                         break;
02611                 /* GRP 4 Eb and callback's */
02612                 case 0xfe:
02613             dyn_get_modrm();
02614                         switch (decode.modrm.reg) {
02615                         case 0x0://INC Eb
02616                         case 0x1://DEC Eb
02617                                 if (decode.modrm.mod<3) {
02618                                         dyn_fill_ea();dyn_read_byte(DREG(EA),DREG(TMPB),false);
02619                                         gen_needcarry();
02620                                         gen_sop_byte(decode.modrm.reg==0 ? SOP_INC : SOP_DEC,DREG(TMPB),0);
02621                                         dyn_write_byte_release(DREG(EA),DREG(TMPB),false);
02622                                         gen_releasereg(DREG(TMPB));
02623                                 } else {
02624                                         gen_needcarry();
02625                                         gen_sop_byte(decode.modrm.reg==0 ? SOP_INC : SOP_DEC,
02626                                                 &DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
02627                                 }
02628                                 break;
02629                         case 0x7:               //CALBACK Iw
02630                                 gen_save_host_direct(&core_dyn.callback,decode_fetchw());
02631                                 dyn_set_eip_end();
02632                                 dyn_reduce_cycles();
02633                                 dyn_save_critical_regs();
02634                                 gen_return(BR_CallBack);
02635                                 dyn_closeblock();
02636                                 goto finish_block;
02637                         }
02638                         break;
02639 
02640                 case 0xff: 
02641                         {
02642             dyn_get_modrm();DynReg * src;
02643                         if (decode.modrm.mod<3) {
02644                                 dyn_fill_ea();
02645                                 dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op);
02646                                 src=DREG(TMPW);
02647                         } else src=&DynRegs[decode.modrm.rm];
02648                         switch (decode.modrm.reg) {
02649                         case 0x0://INC Ev
02650                         case 0x1://DEC Ev
02651                                 gen_needcarry();
02652                                 gen_sop_word(decode.modrm.reg==0 ? SOP_INC : SOP_DEC,decode.big_op,src);
02653                                 if (decode.modrm.mod<3){
02654                                         dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op);
02655                                         gen_releasereg(DREG(TMPW));
02656                                 }
02657                                 break;
02658                         case 0x2:       /* CALL Ev */
02659                                 gen_lea(DREG(TMPB),DREG(EIP),0,0,decode.code-decode.code_start);
02660                                 dyn_push(DREG(TMPB));
02661                                 gen_releasereg(DREG(TMPB));
02662                                 gen_dop_word(DOP_MOV,decode.big_op,DREG(EIP),src);
02663                                 goto core_close_block;
02664                         case 0x4:       /* JMP Ev */
02665                                 gen_dop_word(DOP_MOV,decode.big_op,DREG(EIP),src);
02666                                 goto core_close_block;
02667                         case 0x3:       /* CALL Ep */
02668                         case 0x5:       /* JMP Ep */
02669                                 gen_protectflags();
02670                                 dyn_flags_gen_to_host();
02671                                 gen_lea(DREG(EA),DREG(EA),0,0,decode.big_op ? 4: 2);
02672                                 dyn_read_word(DREG(EA),DREG(EA),false);
02673                                 dyn_set_eip_last_end(DREG(TMPB));
02674                                 dyn_save_critical_regs();
02675                                 gen_call_function(
02676                                         decode.modrm.reg == 3 ? (void*)&CPU_CALL : (void*)&CPU_JMP,
02677                                         decode.big_op ? "%Id%Drw%Drd%Drd" : "%Id%Drw%Drw%Drd",
02678                                         decode.big_op,DREG(EA),DREG(TMPW),DREG(TMPB));
02679                                 dyn_flags_host_to_gen();
02680                                 goto core_close_block;
02681                         case 0x6:               /* PUSH Ev */
02682                                 gen_releasereg(DREG(EA));
02683                                 dyn_push(src);
02684                                 break;
02685                         default:
02686                                 LOG(LOG_CPU,LOG_ERROR)("CPU:GRP5:Illegal opcode 0xff");
02687                                 goto illegalopcode;
02688                         }}
02689                         break;
02690                 default:
02691 #if DYN_LOG
02692 //                      LOG_MSG("Dynamic unhandled opcode %X",opcode);
02693 #endif
02694                         goto illegalopcode;
02695                 }
02696         }
02697         // link to next block because the maximum number of opcodes has been reached
02698         dyn_set_eip_end();
02699         dyn_reduce_cycles();
02700         dyn_save_critical_regs();
02701         gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start));
02702         dyn_closeblock();
02703         goto finish_block;
02704 core_close_block:
02705         dyn_reduce_cycles();
02706         dyn_save_critical_regs();
02707         gen_return(BR_Normal);
02708         dyn_closeblock();
02709         goto finish_block;
02710 illegalopcode:
02711         dyn_set_eip_last();
02712         dyn_reduce_cycles();
02713         dyn_save_critical_regs();
02714         gen_return(BR_Opcode);
02715         dyn_closeblock();
02716         goto finish_block;
02717 #if (C_DEBUG)
02718         dyn_set_eip_last();
02719         dyn_reduce_cycles();
02720         dyn_save_critical_regs();
02721         gen_return(BR_OpcodeFull);
02722         dyn_closeblock();
02723         goto finish_block;
02724 #endif
02725 finish_block:
02726         /* Setup the correct end-address */
02727         decode.active_block->page.end=--decode.page.index;
02728 //      LOG_MSG("Created block size %d start %d end %d",decode.block->cache.size,decode.block->page.start,decode.block->page.end);
02729         return decode.block;
02730 }