📄 decoder.h
字号:
dyn_pop(DREG(EBP),false); gen_releasereg(DREG(TMPW));}static void dyn_segprefix(SegNames seg) { if (GCC_UNLIKELY((Bitu)(decode.segprefix))) IllegalOption("dyn_segprefix"); decode.segprefix=&DynRegs[G_ES+seg];}static void dyn_closeblock(void) { //Shouldn't create empty block normally but let's do it like this gen_protectflags(); dyn_fill_blocks(); cache_closeblock();}static void dyn_normal_exit(BlockReturn code) { gen_protectflags(); dyn_reduce_cycles(); dyn_set_eip_last(); dyn_save_critical_regs(); gen_return(code); dyn_closeblock();}static void dyn_exit_link(Bits eip_change) { gen_protectflags(); gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),(decode.code-decode.code_start)+eip_change); dyn_reduce_cycles(); dyn_save_critical_regs(); gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start)); dyn_closeblock();}static void dyn_branched_exit(BranchTypes btype,Bit32s eip_add) { Bitu eip_base=decode.code-decode.code_start; gen_needflags(); gen_protectflags(); dyn_save_noncritical_regs(); gen_releasereg(DREG(FLAGS)); gen_releasereg(DREG(EIP)); gen_preloadreg(DREG(CYCLES)); gen_preloadreg(DREG(EIP)); DynReg save_cycles,save_eip; dyn_saveregister(DREG(CYCLES),&save_cycles); dyn_saveregister(DREG(EIP),&save_eip); Bit8u * data=gen_create_branch(btype); /* Branch not taken */ dyn_reduce_cycles(); gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),eip_base); gen_releasereg(DREG(CYCLES)); gen_releasereg(DREG(EIP)); gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start)); gen_fill_branch(data); /* Branch taken */ dyn_restoreregister(&save_cycles,DREG(CYCLES)); dyn_restoreregister(&save_eip,DREG(EIP)); dyn_reduce_cycles(); gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),eip_base+eip_add); gen_releasereg(DREG(CYCLES)); gen_releasereg(DREG(EIP)); gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlock,cache.start)); dyn_closeblock();}enum LoopTypes { LOOP_NONE,LOOP_NE,LOOP_E,LOOP_JCXZ};static void dyn_loop(LoopTypes type) { dyn_reduce_cycles(); Bits eip_add=(Bit8s)decode_fetchb(); Bitu eip_base=decode.code-decode.code_start; Bit8u * branch1=0;Bit8u * branch2=0; dyn_save_critical_regs(); switch (type) { case LOOP_E: gen_needflags(); branch1=gen_create_branch(BR_NZ); break; case LOOP_NE: gen_needflags(); branch1=gen_create_branch(BR_Z); break; } gen_protectflags(); switch (type) { case LOOP_E: case LOOP_NE: case LOOP_NONE: gen_sop_word(SOP_DEC,decode.big_addr,DREG(ECX)); gen_releasereg(DREG(ECX)); branch2=gen_create_branch(BR_Z); break; case LOOP_JCXZ: gen_dop_word(DOP_OR,decode.big_addr,DREG(ECX),DREG(ECX)); gen_releasereg(DREG(ECX)); branch2=gen_create_branch(BR_NZ); break; } gen_lea(DREG(EIP),DREG(EIP),0,0,eip_base+eip_add); gen_releasereg(DREG(EIP)); gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start)); if (branch1) { gen_fill_branch(branch1); gen_sop_word(SOP_DEC,decode.big_addr,DREG(ECX)); gen_releasereg(DREG(ECX)); } /* Branch taken */ gen_fill_branch(branch2); gen_lea(DREG(EIP),DREG(EIP),0,0,eip_base); gen_releasereg(DREG(EIP)); gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlock,cache.start)); dyn_closeblock();}static void dyn_ret_near(Bitu bytes) { gen_protectflags(); dyn_reduce_cycles(); dyn_pop(DREG(EIP)); if (bytes) gen_dop_word_imm(DOP_ADD,true,DREG(ESP),bytes); dyn_save_critical_regs(); gen_return(BR_Normal); dyn_closeblock();}static void dyn_call_near_imm(void) { Bits imm; if (decode.big_op) imm=(Bit32s)decode_fetchd(); else imm=(Bit16s)decode_fetchw(); dyn_set_eip_end(DREG(TMPW)); dyn_push(DREG(TMPW)); gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(TMPW),imm); gen_dop_word(DOP_MOV,decode.big_op,DREG(EIP),DREG(TMPW)); dyn_reduce_cycles(); dyn_save_critical_regs(); gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start)); dyn_closeblock();}static void dyn_ret_far(Bitu bytes) { gen_protectflags(); dyn_reduce_cycles(); dyn_set_eip_last_end(DREG(TMPW)); dyn_flags_gen_to_host(); dyn_save_critical_regs(); gen_call_function((void*)&CPU_RET,"%Id%Id%Drd",decode.big_op,bytes,DREG(TMPW)); gen_return_fast(BR_Normal); dyn_closeblock();}static void dyn_call_far_imm(void) { Bitu sel,off; off=decode.big_op ? decode_fetchd() : decode_fetchw(); sel=decode_fetchw(); dyn_reduce_cycles(); dyn_set_eip_last_end(DREG(TMPW)); dyn_flags_gen_to_host(); dyn_save_critical_regs(); gen_call_function((void*)&CPU_CALL,"%Id%Id%Id%Drd",decode.big_op,sel,off,DREG(TMPW)); gen_return_fast(BR_Normal); dyn_closeblock();}static void dyn_jmp_far_imm(void) { Bitu sel,off; gen_protectflags(); off=decode.big_op ? decode_fetchd() : decode_fetchw(); sel=decode_fetchw(); dyn_reduce_cycles(); dyn_set_eip_last_end(DREG(TMPW)); dyn_flags_gen_to_host(); dyn_save_critical_regs(); gen_call_function((void*)&CPU_JMP,"%Id%Id%Id%Drd",decode.big_op,sel,off,DREG(TMPW)); gen_return_fast(BR_Normal); dyn_closeblock();}static void dyn_iret(void) { gen_protectflags(); dyn_flags_gen_to_host(); dyn_reduce_cycles(); dyn_set_eip_last_end(DREG(TMPW)); dyn_save_critical_regs(); gen_call_function((void*)&CPU_IRET,"%Id%Drd",decode.big_op,DREG(TMPW)); gen_return_fast(BR_Iret); dyn_closeblock();}static void dyn_interrupt(Bitu num) { gen_protectflags(); dyn_flags_gen_to_host(); dyn_reduce_cycles(); dyn_set_eip_last_end(DREG(TMPW)); dyn_save_critical_regs(); gen_call_function((void*)&CPU_Interrupt,"%Id%Id%Drd",num,CPU_INT_SOFTWARE,DREG(TMPW)); gen_return_fast(BR_Normal); dyn_closeblock();}static void dyn_add_iocheck(Bitu access_size) { if (cpu.pmode) { gen_call_function((void *)&CPU_IO_Exception,"%Dw%Id",DREG(EDX),access_size); dyn_check_bool_exception_al(); }}static void dyn_add_iocheck_var(Bit8u accessed_port,Bitu access_size) { if (cpu.pmode) { gen_call_function((void *)&CPU_IO_Exception,"%Id%Id",accessed_port,access_size); dyn_check_bool_exception_al(); }}#ifdef X86_DYNFPU_DH_ENABLED#include "dyn_fpu_dh.h"#define dh_fpu_startup() { \ fpu_used=true; \ gen_protectflags(); \ gen_load_host(&dyn_dh_fpu.state_used,DREG(TMPB),4); \ gen_dop_word_imm(DOP_CMP,true,DREG(TMPB),0); \ gen_releasereg(DREG(TMPB)); \ save_info[used_save_info].branch_pos=gen_create_branch_long(BR_Z); \ dyn_savestate(&save_info[used_save_info].state); \ save_info[used_save_info].return_pos=cache.pos; \ save_info[used_save_info].type=fpu_restore; \ used_save_info++; \}#endif#include "dyn_fpu.h"static CacheBlock * CreateCacheBlock(CodePageHandler * codepage,PhysPt start,Bitu max_opcodes) { Bits i;/* Init a load of variables */ decode.code_start=start; decode.code=start; Bitu cycles=0; decode.page.code=codepage; decode.page.index=start&4095; decode.page.wmap=codepage->write_map; decode.page.invmap=codepage->invalidation_map; decode.page.first=start >> 12; decode.active_block=decode.block=cache_openblock(); decode.block->page.start=decode.page.index; codepage->AddCacheBlock(decode.block); gen_save_host_direct(&cache.block.running,(Bit32u)decode.block); for (i=0;i<G_MAX;i++) { DynRegs[i].flags&=~(DYNFLG_ACTIVE|DYNFLG_CHANGED); DynRegs[i].genreg=0; } gen_reinit(); /* Start with the cycles check */ gen_protectflags(); gen_dop_word_imm(DOP_CMP,true,DREG(CYCLES),0); save_info[used_save_info].branch_pos=gen_create_branch_long(BR_LE); save_info[used_save_info].type=cycle_check; used_save_info++; gen_releasereg(DREG(CYCLES)); decode.cycles=0;#ifdef X86_DYNFPU_DH_ENABLED bool fpu_used=false;#endif while (max_opcodes--) {/* Init prefixes */ decode.big_addr=cpu.code.big; decode.big_op=cpu.code.big; decode.segprefix=0; decode.rep=REP_NONE; decode.cycles++; decode.op_start=decode.code;restart_prefix: Bitu opcode; if (!decode.page.invmap) opcode=decode_fetchb(); else { if (decode.page.index<4096) { if (GCC_UNLIKELY(decode.page.invmap[decode.page.index]>=4)) goto illegalopcode; opcode=decode_fetchb(); } else { opcode=decode_fetchb(); if (GCC_UNLIKELY(decode.page.invmap && (decode.page.invmap[decode.page.index-1]>=4))) goto illegalopcode; } } switch (opcode) { case 0x00:dyn_dop_ebgb(DOP_ADD);break; case 0x01:dyn_dop_evgv(DOP_ADD);break; case 0x02:dyn_dop_gbeb(DOP_ADD);break; case 0x03:dyn_dop_gvev(DOP_ADD);break; case 0x04:gen_discardflags();gen_dop_byte_imm(DOP_ADD,DREG(EAX),0,decode_fetchb());break; case 0x05:gen_discardflags();dyn_dop_word_imm(DOP_ADD,decode.big_op,DREG(EAX));break; case 0x06:dyn_push_seg(es);break; case 0x07:dyn_pop_seg(es);break; case 0x08:dyn_dop_ebgb(DOP_OR);break; case 0x09:dyn_dop_evgv(DOP_OR);break; case 0x0a:dyn_dop_gbeb(DOP_OR);break; case 0x0b:dyn_dop_gvev(DOP_OR);break; case 0x0c:gen_discardflags();gen_dop_byte_imm(DOP_OR,DREG(EAX),0,decode_fetchb());break; case 0x0d:gen_discardflags();gen_dop_word_imm(DOP_OR,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());break; case 0x0e:dyn_push_seg(cs);break; case 0x0f: { Bitu dual_code=decode_fetchb(); switch (dual_code) { /* Short conditional jumps */ case 0x80:case 0x81:case 0x82:case 0x83:case 0x84:case 0x85:case 0x86:case 0x87: case 0x88:case 0x89:case 0x8a:case 0x8b:case 0x8c:case 0x8d:case 0x8e:case 0x8f: dyn_branched_exit((BranchTypes)(dual_code&0xf), decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw()); goto finish_block; /* PUSH/POP FS */ case 0xa0:dyn_push_seg(fs);break; case 0xa1:dyn_pop_seg(fs);break; /* SHLD Imm/cl*/ case 0xa4:dyn_dshift_ev_gv(true,true);break; case 0xa5:dyn_dshift_ev_gv(true,false);break; /* PUSH/POP GS */ case 0xa8:dyn_push_seg(gs);break; case 0xa9:dyn_pop_seg(gs);break; /* SHRD Imm/cl*/ case 0xac:dyn_dshift_ev_gv(false,true);break; case 0xad:dyn_dshift_ev_gv(false,false);break; /* Imul Ev,Gv */ case 0xaf:dyn_imul_gvev(0);break; /* LFS,LGS */ case 0xb4:dyn_load_seg_off_ea(fs);break; case 0xb5:dyn_load_seg_off_ea(gs);break; /* MOVZX Gv,Eb/Ew */ case 0xb6:dyn_mov_ev_gb(false);break; case 0xb7:dyn_mov_ev_gw(false);break; /* MOVSX Gv,Eb/Ew */ case 0xbe:dyn_mov_ev_gb(true);break; case 0xbf:dyn_mov_ev_gw(true);break; default: DYN_LOG("Unhandled dual opcode 0F%02X",dual_code); goto illegalopcode; } }break; case 0x10:dyn_dop_ebgb(DOP_ADC);break; case 0x11:dyn_dop_evgv(DOP_ADC);break; case 0x12:dyn_dop_gbeb(DOP_ADC);break; case 0x13:dyn_dop_gvev(DOP_ADC);break; case 0x14:gen_needcarry();gen_dop_byte_imm(DOP_ADC,DREG(EAX),0,decode_fetchb());break; case 0x15:gen_needcarry();gen_dop_word_imm(DOP_ADC,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());break; case 0x16:dyn_push_seg(ss);break; case 0x17:dyn_pop_seg(ss);break; case 0x18:dyn_dop_ebgb(DOP_SBB);break; case 0x19:dyn_dop_evgv(DOP_SBB);break; case 0x1a:dyn_dop_gbeb(DOP_SBB);break; case 0x1b:dyn_dop_gvev(DOP_SBB);break; case 0x1c:gen_needcarry();gen_dop_byte_imm(DOP_SBB,DREG(EAX),0,decode_fetchb());break; case 0x1d:gen_needcarry();gen_dop_word_imm(DOP_SBB,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());break; case 0x1e:dyn_push_seg(ds);break; case 0x1f:dyn_pop_seg(ds);break; case 0x20:dyn_dop_ebgb(DOP_AND);break; case 0x21:dyn_dop_evgv(DOP_AND);break; case 0x22:dyn_dop_gbeb(DOP_AND);break; case 0x23:dyn_dop_gvev(DOP_AND);break; case 0x24:gen_discardflags();gen_dop_byte_imm(DOP_AND,DREG(EAX),0,decode_fetchb());break; case 0x25:gen_discardflags();dyn_dop_word_imm(DOP_AND,decode.big_op,DREG(EAX));break; case 0x26:dyn_segprefix(es);goto restart_prefix; case 0x28:dyn_dop_ebgb(DOP_SUB);break; case 0x29:dyn_dop_evgv(DOP_SUB);break; case 0x2a:dyn_dop_gbeb(DOP_SUB);break; case 0x2b:dyn_dop_gvev(DOP_SUB);break; case 0x2c:gen_discardflags();gen_dop_byte_imm(DOP_SUB,DREG(EAX),0,decode_fetchb());break; case 0x2d:gen_discardflags();gen_dop_word_imm(DOP_SUB,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());break; case 0x2e:dyn_segprefix(cs);goto restart_prefix; case 0x30:dyn_dop_ebgb(DOP_XOR);break; case 0x31:dyn_dop_evgv(DOP_XOR);break; case 0x32:dyn_dop_gbeb(DOP_XOR);break; case 0x33:dyn_dop_gvev(DOP_XOR);break; case 0x34:gen_discardflags();gen_dop_byte_imm(DOP_XOR,DREG(EAX),0,decode_fetchb());break; case 0x35:gen_discardflags();gen_dop_word_imm(DOP_XOR,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());break; case 0x36:dyn_segprefix(ss);goto restart_prefix; case 0x38:dyn_dop_ebgb(DOP_CMP);break; case 0x39:dyn_dop_evgv(DOP_CMP);break; case 0x3a:dyn_dop_gbeb(DOP_CMP);break; case 0x3b:dyn_dop_gvev(DOP_CMP);break; case 0x3c:gen_discardflags();gen_dop_byte_imm(DOP_CMP,DREG(EAX),0,decode_fetchb());break; case 0x3d:gen_discardflags();gen_dop_word_imm(DOP_CMP,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());break; case 0x3e:dyn_segprefix(ds);goto restart_prefix; /* INC/DEC general register */ case 0x40:case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:case 0x47: gen_needcarry();gen_sop_word(SOP_INC,decode.big_op,&DynRegs[opcode&7]); break; case 0x48:case 0x49:case 0x4a:case 0x4b:case 0x4c:case 0x4d:case 0x4e:case 0x4f: gen_needcarry();gen_sop_word(SOP_DEC,decode.big_op,&DynRegs[opcode&7]); break; /* PUSH/POP General register */ case 0x50:case 0x51:case 0x52:case 0x53:case 0x55:case 0x56:case 0x57: dyn_push(&DynRegs[opcode&7]); break; case 0x54: /* PUSH SP is special */ gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(ESP)); dyn_push(DREG(TMPW)); gen_releasereg(DREG(TMPW)); break; case 0x58:case 0x59:case 0x5a:case 0x5b:case 0x5c:case 0x5d:case 0x5e:case 0x5f: dyn_pop(&DynRegs[opcode&7]); break; case 0x60: /* PUSHA */ gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(ESP)); for (i=G_EAX;i<=G_EDI;i++) { dyn_push_unchecked((i!=G_ESP) ? &DynRegs[i] :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -