diff --git a/src/cpu/core_dyn_x86/decoder.h b/src/cpu/core_dyn_x86/decoder.h index 323bc5bf..79a1979c 100644 --- a/src/cpu/core_dyn_x86/decoder.h +++ b/src/cpu/core_dyn_x86/decoder.h @@ -142,7 +142,10 @@ static INLINE void dyn_set_eip_last(void) { } -static void DynRunException(void) { +static void 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; CPU_Exception(cpu.exception.which,cpu.exception.error); } @@ -151,13 +154,11 @@ static void dyn_check_bool_exception(DynReg * check) { gen_dop_byte(DOP_OR,check,0,check,0); branch=gen_create_branch(BR_Z); dyn_savestate(&state); - dyn_flags_gen_to_host(); - dyn_reduce_cycles(); - dyn_set_eip_last(); + if (!decode.cycles) decode.cycles++; dyn_save_critical_regs(); - gen_call_function((void *)&DynRunException,""); - dyn_flags_host_to_gen(); - gen_return(BR_Normal); + if (cpu.code.big) gen_call_function((void *)&DynRunException,"%Id%Id%F",decode.op_start-decode.code_start,decode.cycles); + else gen_call_function((void *)&DynRunException,"%Iw%Id%F",(decode.op_start-decode.code_start)&0xffff,decode.cycles); + gen_return_fast(BR_Normal,false); dyn_loadstate(&state); gen_fill_branch(branch); } @@ -167,13 +168,11 @@ static void dyn_check_bool_exception_al(void) { cache_addw(0xc00a); // or al, al branch=gen_create_branch(BR_Z); dyn_savestate(&state); - dyn_flags_gen_to_host(); - dyn_reduce_cycles(); - dyn_set_eip_last(); + if (!decode.cycles) decode.cycles++; dyn_save_critical_regs(); - gen_call_function((void *)&DynRunException,""); - dyn_flags_host_to_gen(); - gen_return(BR_Normal); + if (cpu.code.big) gen_call_function((void *)&DynRunException,"%Id%Id%F",decode.op_start-decode.code_start,decode.cycles); + else gen_call_function((void *)&DynRunException,"%Iw%Id%F",(decode.op_start-decode.code_start)&0xffff,decode.cycles); + gen_return_fast(BR_Normal,false); dyn_loadstate(&state); gen_fill_branch(branch); } @@ -1122,8 +1121,7 @@ static void dyn_ret_far(Bitu bytes) { dyn_flags_gen_to_host(); dyn_save_critical_regs(); gen_call_function((void*)&CPU_RET,"%Id%Id%Drd",decode.big_op,bytes,DREG(TMPW)); - dyn_flags_host_to_gen(); - gen_return(BR_Normal); + gen_return_fast(BR_Normal); dyn_closeblock(); } @@ -1136,8 +1134,7 @@ static void dyn_call_far_imm(void) { 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)); - dyn_flags_host_to_gen(); - gen_return(BR_Normal); + gen_return_fast(BR_Normal); dyn_closeblock(); } @@ -1151,8 +1148,7 @@ static void dyn_jmp_far_imm(void) { 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)); - dyn_flags_host_to_gen(); - gen_return(BR_Normal); + gen_return_fast(BR_Normal); dyn_closeblock(); } @@ -1163,8 +1159,7 @@ static void dyn_iret(void) { dyn_set_eip_last_end(DREG(TMPW)); dyn_save_critical_regs(); gen_call_function((void*)&CPU_IRET,"%Id%Drd",decode.big_op,DREG(TMPW)); - dyn_flags_host_to_gen(); - gen_return(BR_Normal); + gen_return_fast(BR_Normal); dyn_closeblock(); } @@ -1175,8 +1170,7 @@ static void dyn_interrupt(Bitu num) { 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)); - dyn_flags_host_to_gen(); - gen_return(BR_Normal); + gen_return_fast(BR_Normal); dyn_closeblock(); } diff --git a/src/cpu/core_dyn_x86/risc_x86.h b/src/cpu/core_dyn_x86/risc_x86.h index e7d0f6fa..ba662e6f 100644 --- a/src/cpu/core_dyn_x86/risc_x86.h +++ b/src/cpu/core_dyn_x86/risc_x86.h @@ -591,6 +591,7 @@ static void gen_dshift_cl(bool dword,bool left,DynReg * dr1,DynReg * dr2,DynReg static void gen_call_function(void * func,char * ops,...) { Bits paramcount=0; + bool release_flags=false; struct ParamInfo { char * line; Bitu value; @@ -663,6 +664,9 @@ static void gen_call_function(void * func,char * ops,...) { retparam =&pinfo[pindex]; pinfo[pindex].line=scan; break; + case 'F': /* Release flags from stack */ + release_flags=true; + break; default: IllegalOption("gen_call_function unknown param"); } @@ -677,7 +681,10 @@ static void gen_call_function(void * func,char * ops,...) { /* Restore the params of the stack */ if (paramcount) { cache_addw(0xc483); //add ESP,imm byte - cache_addb(paramcount*4); + cache_addb(paramcount*4+(release_flags?4:0)); + } else if (release_flags) { + cache_addw(0xc483); //add ESP,imm byte + cache_addb(4); } /* Save the return value in correct register */ if (retparam) { @@ -838,8 +845,27 @@ static void gen_mov_host(void * data,DynReg * dr1,Bitu size,Bit8u di1=0) { static void gen_return(BlockReturn retcode) { gen_protectflags(); cache_addb(0x59); //POP ECX, the flags - cache_addb(0xb8); //MOV EAX, retcode - cache_addd(retcode); + if (retcode==0) cache_addw(0xc033); //MOV EAX, 0 + else { + cache_addb(0xb8); //MOV EAX, retcode + cache_addd(retcode); + } + cache_addb(0xc3); //RET +} + +static void gen_return_fast(BlockReturn retcode,bool popflags=true) { + if (GCC_UNLIKELY(x86gen.flagsactive)) IllegalOption("gen_return_fast"); + cache_addw(0x0d8b); //MOV ECX, the flags + cache_addd((Bit32u)&cpu_regs.flags); + if (popflags) { + cache_addw(0xc483); //ADD ESP,4 + cache_addb(0x4); + } + if (retcode==0) cache_addw(0xc033); //MOV EAX, 0 + else { + cache_addb(0xb8); //MOV EAX, retcode + cache_addd(retcode); + } cache_addb(0xc3); //RET }