📄 decoder.h
字号:
/* * Copyright (C) 2002-2007 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#define X86_DYNFPU_DH_ENABLED#define X86_INLINED_MEMACCESSenum REP_Type { REP_NONE=0,REP_NZ,REP_Z};static struct DynDecode { PhysPt code; PhysPt code_start; PhysPt op_start; bool big_op; bool big_addr; REP_Type rep; Bitu cycles; CacheBlock * block; CacheBlock * active_block; struct { CodePageHandler * code; Bitu index; Bit8u * wmap; Bit8u * invmap; Bitu first; } page; struct { Bitu val; Bitu mod; Bitu rm; Bitu reg; } modrm; DynReg * segprefix;} decode;static bool MakeCodePage(Bitu lin_page,CodePageHandler * &cph) { Bit8u rdval; //Ensure page contains memory: if (GCC_UNLIKELY(mem_readb_checked_x86(lin_page << 12,&rdval))) return true; PageHandler * handler=paging.tlb.handler[lin_page]; if (handler->flags & PFLAG_HASCODE) { cph=( CodePageHandler *)handler; return false; } if (handler->flags & PFLAG_NOCODE) { LOG_MSG("DYNX86:Can't run code in this page"); cph=0; return false; } Bitu phys_page=lin_page; if (!PAGING_MakePhysPage(phys_page)) { LOG_MSG("DYNX86:Can't find physpage"); cph=0; return false; } /* Find a free CodePage */ if (!cache.free_pages) { if (cache.used_pages!=decode.page.code) cache.used_pages->ClearRelease(); else { if ((cache.used_pages->next) && (cache.used_pages->next!=decode.page.code)) cache.used_pages->next->ClearRelease(); else { LOG_MSG("DYNX86:Invalid cache links"); cache.used_pages->ClearRelease(); } } } CodePageHandler * cpagehandler=cache.free_pages; cache.free_pages=cache.free_pages->next; cpagehandler->prev=cache.last_page; cpagehandler->next=0; if (cache.last_page) cache.last_page->next=cpagehandler; cache.last_page=cpagehandler; if (!cache.used_pages) cache.used_pages=cpagehandler; cpagehandler->SetupAt(phys_page,handler); MEM_SetPageHandler(phys_page,1,cpagehandler); PAGING_UnlinkPages(lin_page,1); cph=cpagehandler; return false;}static Bit8u decode_fetchb(void) { if (GCC_UNLIKELY(decode.page.index>=4096)) { /* Advance to the next page */ decode.active_block->page.end=4095; /* trigger possible page fault here */ mem_readb((++decode.page.first) << 12); MakeCodePage(decode.page.first,decode.page.code); CacheBlock * newblock=cache_getblock(); decode.active_block->crossblock=newblock; newblock->crossblock=decode.active_block; decode.active_block=newblock; decode.active_block->page.start=0; decode.page.code->AddCrossBlock(decode.active_block); decode.page.wmap=decode.page.code->write_map; decode.page.invmap=decode.page.code->invalidation_map; decode.page.index=0; } decode.page.wmap[decode.page.index]+=0x01; decode.page.index++; decode.code+=1; return mem_readb(decode.code-1);}static Bit16u decode_fetchw(void) { if (GCC_UNLIKELY(decode.page.index>=4095)) { Bit16u val=decode_fetchb(); val|=decode_fetchb() << 8; return val; } *(Bit16u *)&decode.page.wmap[decode.page.index]+=0x0101; decode.code+=2;decode.page.index+=2; return mem_readw(decode.code-2);}static Bit32u decode_fetchd(void) { if (GCC_UNLIKELY(decode.page.index>=4093)) { Bit32u val=decode_fetchb(); val|=decode_fetchb() << 8; val|=decode_fetchb() << 16; val|=decode_fetchb() << 24; return val; /* Advance to the next page */ } *(Bit32u *)&decode.page.wmap[decode.page.index]+=0x01010101; decode.code+=4;decode.page.index+=4; return mem_readd(decode.code-4);}#define START_WMMEM 64static void INLINE decode_increase_wmapmask(Bitu size) { Bitu mapidx; CacheBlock* activecb=decode.active_block; if (GCC_UNLIKELY(!activecb->cache.wmapmask)) { activecb->cache.wmapmask=(Bit8u*)malloc(START_WMMEM); memset(activecb->cache.wmapmask,0,START_WMMEM); activecb->cache.maskstart=decode.page.index; activecb->cache.masklen=START_WMMEM; mapidx=0; } else { mapidx=decode.page.index-activecb->cache.maskstart; if (GCC_UNLIKELY(mapidx+size>=activecb->cache.masklen)) { Bitu newmasklen=activecb->cache.masklen*4; if (newmasklen<mapidx+size) newmasklen=((mapidx+size)&~3)*2; Bit8u* tempmem=(Bit8u*)malloc(newmasklen); memset(tempmem,0,newmasklen); memcpy(tempmem,activecb->cache.wmapmask,activecb->cache.masklen); free(activecb->cache.wmapmask); activecb->cache.wmapmask=tempmem; activecb->cache.masklen=newmasklen; } } switch (size) { case 1 : activecb->cache.wmapmask[mapidx]+=0x01; break; case 2 : (*(Bit16u*)&activecb->cache.wmapmask[mapidx])+=0x0101; break; case 4 : (*(Bit32u*)&activecb->cache.wmapmask[mapidx])+=0x01010101; break; }}static bool decode_fetchb_imm(Bitu & val) { if (decode.page.index<4096) { Bitu index=(decode.code>>12); if (paging.tlb.read[index]) { val=(Bitu)(paging.tlb.read[index]+decode.code); decode_increase_wmapmask(1); decode.code++; decode.page.index++; return true; } } val=(Bit32u)decode_fetchb(); return false;}static bool decode_fetchw_imm(Bitu & val) { if (decode.page.index<4095) { Bitu index=(decode.code>>12); if (paging.tlb.read[index]) { val=(Bitu)(paging.tlb.read[index]+decode.code); decode_increase_wmapmask(2); decode.code+=2; decode.page.index+=2; return true; } } val=decode_fetchw(); return false;}static bool decode_fetchd_imm(Bitu & val) { if (decode.page.index<4093) { Bitu index=(decode.code>>12); if (paging.tlb.read[index]) { val=(Bitu)(paging.tlb.read[index]+decode.code); decode_increase_wmapmask(4); decode.code+=4; decode.page.index+=4; return true; } } val=decode_fetchd(); return false;}static void dyn_reduce_cycles(void) { gen_protectflags(); if (!decode.cycles) decode.cycles++; gen_dop_word_imm(DOP_SUB,true,DREG(CYCLES),decode.cycles);}static void dyn_save_noncritical_regs(void) { gen_releasereg(DREG(EAX)); gen_releasereg(DREG(ECX)); gen_releasereg(DREG(EDX)); gen_releasereg(DREG(EBX)); gen_releasereg(DREG(ESP)); gen_releasereg(DREG(EBP)); gen_releasereg(DREG(ESI)); gen_releasereg(DREG(EDI));}static void dyn_save_critical_regs(void) { dyn_save_noncritical_regs(); gen_releasereg(DREG(FLAGS)); gen_releasereg(DREG(EIP)); gen_releasereg(DREG(CYCLES));}static void dyn_set_eip_last_end(DynReg * endreg) { gen_protectflags(); gen_lea(endreg,DREG(EIP),0,0,decode.code-decode.code_start); gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),decode.op_start-decode.code_start);}static INLINE void dyn_set_eip_end(void) { gen_protectflags(); gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(EIP),decode.code-decode.code_start);}static INLINE void dyn_set_eip_end(DynReg * endreg) { gen_protectflags(); gen_dop_word(DOP_MOV,cpu.code.big,DREG(TMPW),DREG(EIP)); gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(TMPW),decode.code-decode.code_start);}static INLINE void dyn_set_eip_last(void) { gen_protectflags(); gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(EIP),decode.op_start-decode.code_start);}enum save_info_type {exception, cycle_check, normal, fpu_restore};static struct { save_info_type type; DynState state; Bit8u * branch_pos; Bit32u eip_change; Bitu cycles; Bit8u * return_pos;} save_info[512];Bitu used_save_info=0;static BlockReturn DynRunException(Bit32u eip_add,Bit32u cycle_sub,Bit32u dflags) { reg_flags=(dflags&FMASK_TEST) | (reg_flags&(~FMASK_TEST)); reg_eip+=eip_add; CPU_Cycles-=cycle_sub; if (cpu.exception.which==SMC_CURRENT_BLOCK) return BR_SMCBlock; CPU_Exception(cpu.exception.which,cpu.exception.error); return BR_Normal;}static void dyn_check_bool_exception(DynReg * check) { gen_dop_byte(DOP_OR,check,0,check,0); save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ); dyn_savestate(&save_info[used_save_info].state); if (!decode.cycles) decode.cycles++; save_info[used_save_info].cycles=decode.cycles; save_info[used_save_info].eip_change=decode.op_start-decode.code_start; if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff; save_info[used_save_info].type=exception; used_save_info++;}static void dyn_check_bool_exception_al(void) { cache_addw(0xc00a); // or al, al save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ); dyn_savestate(&save_info[used_save_info].state); if (!decode.cycles) decode.cycles++; save_info[used_save_info].cycles=decode.cycles; save_info[used_save_info].eip_change=decode.op_start-decode.code_start; if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff; save_info[used_save_info].type=exception; used_save_info++;}#include "pic.h"static void dyn_check_irqrequest(void) { gen_load_host(&PIC_IRQCheck,DREG(TMPB),4); gen_dop_word(DOP_OR,true,DREG(TMPB),DREG(TMPB)); save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ); gen_releasereg(DREG(TMPB)); dyn_savestate(&save_info[used_save_info].state); if (!decode.cycles) decode.cycles++; save_info[used_save_info].cycles=decode.cycles; save_info[used_save_info].eip_change=decode.code-decode.code_start; if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff; save_info[used_save_info].type=normal; used_save_info++;}static void dyn_check_bool_exception_ne(void) { save_info[used_save_info].branch_pos=gen_create_branch_long(BR_Z); dyn_savestate(&save_info[used_save_info].state); if (!decode.cycles) decode.cycles++; save_info[used_save_info].cycles=decode.cycles; save_info[used_save_info].eip_change=decode.op_start-decode.code_start; if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff; save_info[used_save_info].type=exception; used_save_info++;}static void dyn_fill_blocks(void) { for (Bitu sct=0; sct<used_save_info; sct++) { gen_fill_branch_long(save_info[sct].branch_pos); switch (save_info[sct].type) { case exception: dyn_loadstate(&save_info[sct].state); decode.cycles=save_info[sct].cycles; dyn_save_critical_regs(); if (cpu.code.big) gen_call_function((void *)&DynRunException,"%Id%Id%F",save_info[sct].eip_change,save_info[sct].cycles); else gen_call_function((void *)&DynRunException,"%Iw%Id%F",save_info[sct].eip_change,save_info[sct].cycles); gen_return_fast(BR_Normal,true); break; case cycle_check: gen_return(BR_Cycles); break; case normal: dyn_loadstate(&save_info[sct].state); gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),save_info[sct].eip_change); dyn_save_critical_regs(); gen_return(BR_Cycles); break; case fpu_restore: dyn_loadstate(&save_info[sct].state); gen_load_host(&dyn_dh_fpu.state_used,DREG(TMPB),4); gen_sop_word(SOP_INC,true,DREG(TMPB)); GenReg * gr1=FindDynReg(DREG(TMPB)); cache_addb(0xdd); // FRSTOR fpu.state (fpu_restore) cache_addb(0x25); cache_addd((Bit32u)(&(dyn_dh_fpu.state[0]))); cache_addb(0x89); // mov fpu.state_used,1 cache_addb(0x05|(gr1->index<<3)); cache_addd((Bit32u)(&(dyn_dh_fpu.state_used))); gen_releasereg(DREG(TMPB)); dyn_synchstate(&save_info[sct].state); gen_create_jump(save_info[sct].return_pos); break; } } used_save_info=0;}#if !defined(X86_INLINED_MEMACCESS)static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) { gen_protectflags(); gen_call_function((void *)&mem_readb_checked_x86,"%Dd%Id",addr,&core_dyn.readdata); dyn_check_bool_exception_al(); gen_mov_host(&core_dyn.readdata,dst,1,high);}static void dyn_write_byte(DynReg * addr,DynReg * val,Bitu high) { gen_protectflags(); if (high) gen_call_function((void *)&mem_writeb_checked_x86,"%Dd%Dh",addr,val); else gen_call_function((void *)&mem_writeb_checked_x86,"%Dd%Dd",addr,val); dyn_check_bool_exception_al();}static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) { gen_protectflags(); if (dword) gen_call_function((void *)&mem_readd_checked_x86,"%Dd%Id",addr,&core_dyn.readdata); else gen_call_function((void *)&mem_readw_checked_x86,"%Dd%Id",addr,&core_dyn.readdata); dyn_check_bool_exception_al(); gen_mov_host(&core_dyn.readdata,dst,dword?4:2);}static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) { gen_protectflags(); if (dword) gen_call_function((void *)&mem_writed_checked_x86,"%Dd%Dd",addr,val); else gen_call_function((void *)&mem_writew_checked_x86,"%Dd%Dd",addr,val); dyn_check_bool_exception_al();}static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) { gen_protectflags(); gen_call_function((void *)&mem_readb_checked_x86,"%Ddr%Id",addr,&core_dyn.readdata); dyn_check_bool_exception_al(); gen_mov_host(&core_dyn.readdata,dst,1,high);}static void dyn_write_byte_release(DynReg * addr,DynReg * val,Bitu high) { gen_protectflags(); if (high) gen_call_function((void *)&mem_writeb_checked_x86,"%Ddr%Dh",addr,val); else gen_call_function((void *)&mem_writeb_checked_x86,"%Ddr%Dd",addr,val); dyn_check_bool_exception_al();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -