1
0
Fork 0

move part of flags filling into backend; replace simple-function calls with code if possible

during flags invalidation pass (thanks to crazyc); work around fpu bug (x86_64 only)


Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2930
This commit is contained in:
Sebastian Strohhäcker 2007-07-22 18:48:54 +00:00
parent 2773ef7adf
commit 60292aed8b
6 changed files with 161 additions and 72 deletions

View file

@ -48,6 +48,7 @@
#include "debug.h"
#include "paging.h"
#include "inout.h"
#include "lazyflags.h"
#define CACHE_MAXSIZE (4096)
#define CACHE_TOTAL (1024*1024*8)

View file

@ -1029,16 +1029,15 @@ static void gen_restore_reg(HostReg reg,HostReg dest_reg) {
#include "lazyflags.h"
// flags optimization functions
// they try to find out if a function can be replaced by another
// one that does not generate any flags at all
static Bitu mf_functions_num=0;
static struct {
DRC_PTR_SIZE_IM pos;
Bit32u fct_ptr;
Bit8u* pos;
void* fct_ptr;
Bitu ftype;
} mf_functions[64];
static void InitFlagsOptimization(void) {
@ -1051,7 +1050,7 @@ static void InitFlagsOptimization(void) {
static void InvalidateFlags(void) {
#ifdef DRC_FLAGS_INVALIDATION
for (Bitu ct=0; ct<mf_functions_num; ct++) {
*(Bit32u*)(mf_functions[ct].pos)=(Bit32u)(mf_functions[ct].fct_ptr);
gen_fill_function_ptr(mf_functions[ct].pos,mf_functions[ct].fct_ptr,mf_functions[ct].ftype);
}
mf_functions_num=0;
#endif
@ -1060,24 +1059,26 @@ static void InvalidateFlags(void) {
// replace all queued functions with their simpler variants
// because the current instruction destroys all condition flags and
// the flags are not required before
static void InvalidateFlags(void* current_simple_function) {
static void InvalidateFlags(void* current_simple_function,Bitu flags_type) {
#ifdef DRC_FLAGS_INVALIDATION
for (Bitu ct=0; ct<mf_functions_num; ct++) {
*(Bit32u*)(mf_functions[ct].pos)=(Bit32u)(mf_functions[ct].fct_ptr);
gen_fill_function_ptr(mf_functions[ct].pos,mf_functions[ct].fct_ptr,mf_functions[ct].ftype);
}
mf_functions_num=1;
mf_functions[0].pos=(DRC_PTR_SIZE_IM)cache.pos+1;
mf_functions[0].fct_ptr=(Bit32u)current_simple_function - (Bit32u)mf_functions[0].pos-4;
mf_functions[0].pos=cache.pos;
mf_functions[0].fct_ptr=current_simple_function;
mf_functions[0].ftype=flags_type;
#endif
}
// enqueue this instruction, if later an instruction is encountered that
// destroys all condition flags and the flags weren't needed in-between
// this function can be replaced by a simpler one as well
static void InvalidateFlagsPartially(void* current_simple_function) {
static void InvalidateFlagsPartially(void* current_simple_function,Bitu flags_type) {
#ifdef DRC_FLAGS_INVALIDATION
mf_functions[mf_functions_num].pos=(DRC_PTR_SIZE_IM)cache.pos+1;
mf_functions[mf_functions_num].fct_ptr=(Bit32u)current_simple_function - (Bit32u)mf_functions[mf_functions_num].pos-4;
mf_functions[mf_functions_num].pos=cache.pos;
mf_functions[mf_functions_num].fct_ptr=current_simple_function;
mf_functions[mf_functions_num].ftype=flags_type;
mf_functions_num++;
#endif
}
@ -1085,10 +1086,11 @@ static void InvalidateFlagsPartially(void* current_simple_function) {
// enqueue this instruction, if later an instruction is encountered that
// destroys all condition flags and the flags weren't needed in-between
// this function can be replaced by a simpler one as well
static void InvalidateFlagsPartially(void* current_simple_function,DRC_PTR_SIZE_IM cpos) {
static void InvalidateFlagsPartially(void* current_simple_function,DRC_PTR_SIZE_IM cpos,Bitu flags_type) {
#ifdef DRC_FLAGS_INVALIDATION
mf_functions[mf_functions_num].pos=cpos;
mf_functions[mf_functions_num].fct_ptr=(Bit32u)current_simple_function - (Bit32u)mf_functions[mf_functions_num].pos-4;
mf_functions[mf_functions_num].pos=(Bit8u*)cpos;
mf_functions[mf_functions_num].fct_ptr=current_simple_function;
mf_functions[mf_functions_num].ftype=flags_type;
mf_functions_num++;
#endif
}

View file

@ -505,8 +505,8 @@ static void dyn_fpu_esc5(){
switch(decode.modrm.reg){
case 0x00: /* FLD double real*/
gen_call_function_raw((void*)&FPU_PREP_PUSH);
gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
dyn_fill_ea(FC_OP1);
gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
gen_call_function_RR((void*)&FPU_FLD_F64,FC_OP1,FC_OP2);
break;
case 0x01: /* FISTTP longint*/

View file

@ -393,41 +393,41 @@ static void DRC_CALL_CONV dynrec_test_dword_simple(Bit32u op1,Bit32u op2) {
static void dyn_dop_byte_gencall(DualOps op) {
switch (op) {
case DOP_ADD:
InvalidateFlags((void*)&dynrec_add_byte_simple);
InvalidateFlags((void*)&dynrec_add_byte_simple,t_ADDb);
gen_call_function_raw((void*)&dynrec_add_byte);
break;
case DOP_ADC:
AcquireFlags(FLAG_CF);
InvalidateFlagsPartially((void*)&dynrec_adc_byte_simple);
InvalidateFlagsPartially((void*)&dynrec_adc_byte_simple,t_ADCb);
gen_call_function_raw((void*)&dynrec_adc_byte);
break;
case DOP_SUB:
InvalidateFlags((void*)&dynrec_sub_byte_simple);
InvalidateFlags((void*)&dynrec_sub_byte_simple,t_SUBb);
gen_call_function_raw((void*)&dynrec_sub_byte);
break;
case DOP_SBB:
AcquireFlags(FLAG_CF);
InvalidateFlagsPartially((void*)&dynrec_sbb_byte_simple);
InvalidateFlagsPartially((void*)&dynrec_sbb_byte_simple,t_SBBb);
gen_call_function_raw((void*)&dynrec_sbb_byte);
break;
case DOP_CMP:
InvalidateFlags((void*)&dynrec_cmp_byte_simple);
InvalidateFlags((void*)&dynrec_cmp_byte_simple,t_CMPb);
gen_call_function_raw((void*)&dynrec_cmp_byte);
break;
case DOP_XOR:
InvalidateFlags((void*)&dynrec_xor_byte_simple);
InvalidateFlags((void*)&dynrec_xor_byte_simple,t_XORb);
gen_call_function_raw((void*)&dynrec_xor_byte);
break;
case DOP_AND:
InvalidateFlags((void*)&dynrec_and_byte_simple);
InvalidateFlags((void*)&dynrec_and_byte_simple,t_ANDb);
gen_call_function_raw((void*)&dynrec_and_byte);
break;
case DOP_OR:
InvalidateFlags((void*)&dynrec_or_byte_simple);
InvalidateFlags((void*)&dynrec_or_byte_simple,t_ORb);
gen_call_function_raw((void*)&dynrec_or_byte);
break;
case DOP_TEST:
InvalidateFlags((void*)&dynrec_test_byte_simple);
InvalidateFlags((void*)&dynrec_test_byte_simple,t_TESTb);
gen_call_function_raw((void*)&dynrec_test_byte);
break;
default: IllegalOptionDynrec("dyn_dop_byte_gencall");
@ -438,41 +438,41 @@ static void dyn_dop_word_gencall(DualOps op,bool dword) {
if (dword) {
switch (op) {
case DOP_ADD:
InvalidateFlags((void*)&dynrec_add_dword_simple);
InvalidateFlags((void*)&dynrec_add_dword_simple,t_ADDd);
gen_call_function_raw((void*)&dynrec_add_dword);
break;
case DOP_ADC:
AcquireFlags(FLAG_CF);
InvalidateFlagsPartially((void*)&dynrec_adc_dword_simple);
InvalidateFlagsPartially((void*)&dynrec_adc_dword_simple,t_ADCd);
gen_call_function_raw((void*)&dynrec_adc_dword);
break;
case DOP_SUB:
InvalidateFlags((void*)&dynrec_sub_dword_simple);
InvalidateFlags((void*)&dynrec_sub_dword_simple,t_SUBd);
gen_call_function_raw((void*)&dynrec_sub_dword);
break;
case DOP_SBB:
AcquireFlags(FLAG_CF);
InvalidateFlagsPartially((void*)&dynrec_sbb_dword_simple);
InvalidateFlagsPartially((void*)&dynrec_sbb_dword_simple,t_SBBd);
gen_call_function_raw((void*)&dynrec_sbb_dword);
break;
case DOP_CMP:
InvalidateFlags((void*)&dynrec_cmp_dword_simple);
InvalidateFlags((void*)&dynrec_cmp_dword_simple,t_CMPd);
gen_call_function_raw((void*)&dynrec_cmp_dword);
break;
case DOP_XOR:
InvalidateFlags((void*)&dynrec_xor_dword_simple);
InvalidateFlags((void*)&dynrec_xor_dword_simple,t_XORd);
gen_call_function_raw((void*)&dynrec_xor_dword);
break;
case DOP_AND:
InvalidateFlags((void*)&dynrec_and_dword_simple);
InvalidateFlags((void*)&dynrec_and_dword_simple,t_ANDd);
gen_call_function_raw((void*)&dynrec_and_dword);
break;
case DOP_OR:
InvalidateFlags((void*)&dynrec_or_dword_simple);
InvalidateFlags((void*)&dynrec_or_dword_simple,t_ORd);
gen_call_function_raw((void*)&dynrec_or_dword);
break;
case DOP_TEST:
InvalidateFlags((void*)&dynrec_test_dword_simple);
InvalidateFlags((void*)&dynrec_test_dword_simple,t_TESTd);
gen_call_function_raw((void*)&dynrec_test_dword);
break;
default: IllegalOptionDynrec("dyn_dop_dword_gencall");
@ -480,41 +480,41 @@ static void dyn_dop_word_gencall(DualOps op,bool dword) {
} else {
switch (op) {
case DOP_ADD:
InvalidateFlags((void*)&dynrec_add_word_simple);
InvalidateFlags((void*)&dynrec_add_word_simple,t_ADDw);
gen_call_function_raw((void*)&dynrec_add_word);
break;
case DOP_ADC:
AcquireFlags(FLAG_CF);
InvalidateFlagsPartially((void*)&dynrec_adc_word_simple);
InvalidateFlagsPartially((void*)&dynrec_adc_word_simple,t_ADCw);
gen_call_function_raw((void*)&dynrec_adc_word);
break;
case DOP_SUB:
InvalidateFlags((void*)&dynrec_sub_word_simple);
InvalidateFlags((void*)&dynrec_sub_word_simple,t_SUBw);
gen_call_function_raw((void*)&dynrec_sub_word);
break;
case DOP_SBB:
AcquireFlags(FLAG_CF);
InvalidateFlagsPartially((void*)&dynrec_sbb_word_simple);
InvalidateFlagsPartially((void*)&dynrec_sbb_word_simple,t_SBBw);
gen_call_function_raw((void*)&dynrec_sbb_word);
break;
case DOP_CMP:
InvalidateFlags((void*)&dynrec_cmp_word_simple);
InvalidateFlags((void*)&dynrec_cmp_word_simple,t_CMPw);
gen_call_function_raw((void*)&dynrec_cmp_word);
break;
case DOP_XOR:
InvalidateFlags((void*)&dynrec_xor_word_simple);
InvalidateFlags((void*)&dynrec_xor_word_simple,t_XORw);
gen_call_function_raw((void*)&dynrec_xor_word);
break;
case DOP_AND:
InvalidateFlags((void*)&dynrec_and_word_simple);
InvalidateFlags((void*)&dynrec_and_word_simple,t_ANDw);
gen_call_function_raw((void*)&dynrec_and_word);
break;
case DOP_OR:
InvalidateFlags((void*)&dynrec_or_word_simple);
InvalidateFlags((void*)&dynrec_or_word_simple,t_ORw);
gen_call_function_raw((void*)&dynrec_or_word);
break;
case DOP_TEST:
InvalidateFlags((void*)&dynrec_test_word_simple);
InvalidateFlags((void*)&dynrec_test_word_simple,t_TESTw);
gen_call_function_raw((void*)&dynrec_test_word);
break;
default: IllegalOptionDynrec("dyn_dop_word_gencall");
@ -665,18 +665,18 @@ static Bit32u DRC_CALL_CONV dynrec_neg_dword_simple(Bit32u op) {
static void dyn_sop_byte_gencall(SingleOps op) {
switch (op) {
case SOP_INC:
InvalidateFlagsPartially((void*)&dynrec_inc_byte_simple);
InvalidateFlagsPartially((void*)&dynrec_inc_byte_simple,t_INCb);
gen_call_function_raw((void*)&dynrec_inc_byte);
break;
case SOP_DEC:
InvalidateFlagsPartially((void*)&dynrec_dec_byte_simple);
InvalidateFlagsPartially((void*)&dynrec_dec_byte_simple,t_DECb);
gen_call_function_raw((void*)&dynrec_dec_byte);
break;
case SOP_NOT:
gen_call_function_raw((void*)&dynrec_not_byte);
break;
case SOP_NEG:
InvalidateFlags((void*)&dynrec_neg_byte_simple);
InvalidateFlags((void*)&dynrec_neg_byte_simple,t_NEGb);
gen_call_function_raw((void*)&dynrec_neg_byte);
break;
default: IllegalOptionDynrec("dyn_sop_byte_gencall");
@ -687,18 +687,18 @@ static void dyn_sop_word_gencall(SingleOps op,bool dword) {
if (dword) {
switch (op) {
case SOP_INC:
InvalidateFlagsPartially((void*)&dynrec_inc_dword_simple);
InvalidateFlagsPartially((void*)&dynrec_inc_dword_simple,t_INCd);
gen_call_function_raw((void*)&dynrec_inc_dword);
break;
case SOP_DEC:
InvalidateFlagsPartially((void*)&dynrec_dec_dword_simple);
InvalidateFlagsPartially((void*)&dynrec_dec_dword_simple,t_DECd);
gen_call_function_raw((void*)&dynrec_dec_dword);
break;
case SOP_NOT:
gen_call_function_raw((void*)&dynrec_not_dword);
break;
case SOP_NEG:
InvalidateFlags((void*)&dynrec_neg_dword_simple);
InvalidateFlags((void*)&dynrec_neg_dword_simple,t_NEGd);
gen_call_function_raw((void*)&dynrec_neg_dword);
break;
default: IllegalOptionDynrec("dyn_sop_dword_gencall");
@ -706,18 +706,18 @@ static void dyn_sop_word_gencall(SingleOps op,bool dword) {
} else {
switch (op) {
case SOP_INC:
InvalidateFlagsPartially((void*)&dynrec_inc_word_simple);
InvalidateFlagsPartially((void*)&dynrec_inc_word_simple,t_INCw);
gen_call_function_raw((void*)&dynrec_inc_word);
break;
case SOP_DEC:
InvalidateFlagsPartially((void*)&dynrec_dec_word_simple);
InvalidateFlagsPartially((void*)&dynrec_dec_word_simple,t_DECw);
gen_call_function_raw((void*)&dynrec_dec_word);
break;
case SOP_NOT:
gen_call_function_raw((void*)&dynrec_not_word);
break;
case SOP_NEG:
InvalidateFlags((void*)&dynrec_neg_word_simple);
InvalidateFlags((void*)&dynrec_neg_word_simple,t_NEGw);
gen_call_function_raw((void*)&dynrec_neg_word);
break;
default: IllegalOptionDynrec("dyn_sop_word_gencall");
@ -1113,11 +1113,11 @@ static Bit32u DRC_CALL_CONV dynrec_sar_dword_simple(Bit32u op1,Bit8u op2) {
static void dyn_shift_byte_gencall(ShiftOps op) {
switch (op) {
case SHIFT_ROL:
InvalidateFlagsPartially((void*)&dynrec_rol_byte_simple);
InvalidateFlagsPartially((void*)&dynrec_rol_byte_simple,t_ROLb);
gen_call_function_raw((void*)&dynrec_rol_byte);
break;
case SHIFT_ROR:
InvalidateFlagsPartially((void*)&dynrec_ror_byte_simple);
InvalidateFlagsPartially((void*)&dynrec_ror_byte_simple,t_RORb);
gen_call_function_raw((void*)&dynrec_ror_byte);
break;
case SHIFT_RCL:
@ -1130,15 +1130,15 @@ static void dyn_shift_byte_gencall(ShiftOps op) {
break;
case SHIFT_SHL:
case SHIFT_SAL:
InvalidateFlagsPartially((void*)&dynrec_shl_byte_simple);
InvalidateFlagsPartially((void*)&dynrec_shl_byte_simple,t_SHLb);
gen_call_function_raw((void*)&dynrec_shl_byte);
break;
case SHIFT_SHR:
InvalidateFlagsPartially((void*)&dynrec_shr_byte_simple);
InvalidateFlagsPartially((void*)&dynrec_shr_byte_simple,t_SHRb);
gen_call_function_raw((void*)&dynrec_shr_byte);
break;
case SHIFT_SAR:
InvalidateFlagsPartially((void*)&dynrec_sar_byte_simple);
InvalidateFlagsPartially((void*)&dynrec_sar_byte_simple,t_SARb);
gen_call_function_raw((void*)&dynrec_sar_byte);
break;
default: IllegalOptionDynrec("dyn_shift_byte_gencall");
@ -1149,11 +1149,11 @@ static void dyn_shift_word_gencall(ShiftOps op,bool dword) {
if (dword) {
switch (op) {
case SHIFT_ROL:
InvalidateFlagsPartially((void*)&dynrec_rol_dword_simple);
InvalidateFlagsPartially((void*)&dynrec_rol_dword_simple,t_ROLd);
gen_call_function_raw((void*)&dynrec_rol_dword);
break;
case SHIFT_ROR:
InvalidateFlagsPartially((void*)&dynrec_ror_dword_simple);
InvalidateFlagsPartially((void*)&dynrec_ror_dword_simple,t_RORd);
gen_call_function_raw((void*)&dynrec_ror_dword);
break;
case SHIFT_RCL:
@ -1166,15 +1166,15 @@ static void dyn_shift_word_gencall(ShiftOps op,bool dword) {
break;
case SHIFT_SHL:
case SHIFT_SAL:
InvalidateFlagsPartially((void*)&dynrec_shl_dword_simple);
InvalidateFlagsPartially((void*)&dynrec_shl_dword_simple,t_SHLd);
gen_call_function_raw((void*)&dynrec_shl_dword);
break;
case SHIFT_SHR:
InvalidateFlagsPartially((void*)&dynrec_shr_dword_simple);
InvalidateFlagsPartially((void*)&dynrec_shr_dword_simple,t_SHRd);
gen_call_function_raw((void*)&dynrec_shr_dword);
break;
case SHIFT_SAR:
InvalidateFlagsPartially((void*)&dynrec_sar_dword_simple);
InvalidateFlagsPartially((void*)&dynrec_sar_dword_simple,t_SARd);
gen_call_function_raw((void*)&dynrec_sar_dword);
break;
default: IllegalOptionDynrec("dyn_shift_dword_gencall");
@ -1182,11 +1182,11 @@ static void dyn_shift_word_gencall(ShiftOps op,bool dword) {
} else {
switch (op) {
case SHIFT_ROL:
InvalidateFlagsPartially((void*)&dynrec_rol_word_simple);
InvalidateFlagsPartially((void*)&dynrec_rol_word_simple,t_ROLw);
gen_call_function_raw((void*)&dynrec_rol_word);
break;
case SHIFT_ROR:
InvalidateFlagsPartially((void*)&dynrec_ror_word_simple);
InvalidateFlagsPartially((void*)&dynrec_ror_word_simple,t_RORw);
gen_call_function_raw((void*)&dynrec_ror_word);
break;
case SHIFT_RCL:
@ -1199,15 +1199,15 @@ static void dyn_shift_word_gencall(ShiftOps op,bool dword) {
break;
case SHIFT_SHL:
case SHIFT_SAL:
InvalidateFlagsPartially((void*)&dynrec_shl_word_simple);
InvalidateFlagsPartially((void*)&dynrec_shl_word_simple,t_SHLw);
gen_call_function_raw((void*)&dynrec_shl_word);
break;
case SHIFT_SHR:
InvalidateFlagsPartially((void*)&dynrec_shr_word_simple);
InvalidateFlagsPartially((void*)&dynrec_shr_word_simple,t_SHRw);
gen_call_function_raw((void*)&dynrec_shr_word);
break;
case SHIFT_SAR:
InvalidateFlagsPartially((void*)&dynrec_sar_word_simple);
InvalidateFlagsPartially((void*)&dynrec_sar_word_simple,t_SARw);
gen_call_function_raw((void*)&dynrec_sar_word);
break;
default: IllegalOptionDynrec("dyn_shift_word_gencall");
@ -1298,20 +1298,20 @@ static Bit32u DRC_CALL_CONV dynrec_dshr_dword_simple(Bit32u op1,Bit32u op2,Bit8u
static void dyn_dpshift_word_gencall(bool left) {
if (left) {
DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshl_word,FC_RETOP);
InvalidateFlagsPartially((void*)&dynrec_dshl_word_simple,proc_addr);
InvalidateFlagsPartially((void*)&dynrec_dshl_word_simple,proc_addr,t_DSHLw);
} else {
DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshr_word,FC_RETOP);
InvalidateFlagsPartially((void*)&dynrec_dshr_word_simple,proc_addr);
InvalidateFlagsPartially((void*)&dynrec_dshr_word_simple,proc_addr,t_DSHRw);
}
}
static void dyn_dpshift_dword_gencall(bool left) {
if (left) {
DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshl_dword,FC_RETOP);
InvalidateFlagsPartially((void*)&dynrec_dshl_dword_simple,proc_addr);
InvalidateFlagsPartially((void*)&dynrec_dshl_dword_simple,proc_addr,t_DSHLd);
} else {
DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshr_dword,FC_RETOP);
InvalidateFlagsPartially((void*)&dynrec_dshr_dword_simple,proc_addr);
InvalidateFlagsPartially((void*)&dynrec_dshr_dword_simple,proc_addr,t_DSHRd);
}
}

View file

@ -25,6 +25,8 @@
// try to use non-flags generating functions if possible
// #define DRC_FLAGS_INVALIDATION
// try to replace _simple functions by code
// #define DRC_FLAGS_INVALIDATION_DCODE
// type with the same size as a pointer
#define DRC_PTR_SIZE_IM Bit64u
@ -586,3 +588,11 @@ static void gen_run_code(void) {
static void gen_return_function(void) {
cache_addb(0xc3); // ret
}
#ifdef DRC_FLAGS_INVALIDATION
// called when a call to a function can be replaced by a
// call to a simpler function
static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) {
*(Bit64u*)(pos+2)=(Bit64u)fct_ptr;
}
#endif

View file

@ -25,6 +25,8 @@
// try to use non-flags generating functions if possible
#define DRC_FLAGS_INVALIDATION
// try to replace _simple functions by code
#define DRC_FLAGS_INVALIDATION_DCODE
// type with the same size as a pointer
#define DRC_PTR_SIZE_IM Bit32u
@ -301,9 +303,9 @@ static void INLINE gen_call_function_raw(void * func) {
// note: the parameters are loaded in the architecture specific way
// using the gen_load_param_ functions below
static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) {
Bit32u proc_addr=(Bit32u)cache.pos;
// Do the actual call to the procedure
cache_addb(0xe8);
Bit32u proc_addr=(Bit32u)cache.pos;
cache_addd((Bit32u)func - (Bit32u)cache.pos-4);
// Restore the params of the stack
@ -429,3 +431,77 @@ static void gen_run_code(void) {
static void gen_return_function(void) {
cache_addb(0xc3); // ret
}
#ifdef DRC_FLAGS_INVALIDATION
// called when a call to a function can be replaced by a
// call to a simpler function
static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) {
#ifdef DRC_FLAGS_INVALIDATION_DCODE
// try to avoid function calls but rather directly fill in code
switch (flags_type) {
case t_ADDb:
case t_ADDw:
case t_ADDd:
*(Bit32u*)pos=0xc203c18b;
*(pos+4)=0x90;
break;
case t_ORb:
case t_ORw:
case t_ORd:
*(Bit32u*)pos=0xc20bc18b;
*(pos+4)=0x90;
break;
case t_ANDb:
case t_ANDw:
case t_ANDd:
*(Bit32u*)pos=0xc223c18b;
*(pos+4)=0x90;
break;
case t_SUBb:
case t_SUBw:
case t_SUBd:
*(Bit32u*)pos=0xc22bc18b;
*(pos+4)=0x90;
break;
case t_XORb:
case t_XORw:
case t_XORd:
*(Bit32u*)pos=0xc233c18b;
*(pos+4)=0x90;
break;
case t_CMPb:
case t_CMPw:
case t_CMPd:
case t_TESTb:
case t_TESTw:
case t_TESTd:
*(Bit32u*)pos=0x909003eb;
*(pos+4)=0x90;
break;
case t_INCb:
case t_INCw:
case t_INCd:
*(Bit32u*)pos=0x9040c18b;
*(pos+4)=0x90;
break;
case t_DECb:
case t_DECw:
case t_DECd:
*(Bit32u*)pos=0x9048c18b;
*(pos+4)=0x90;
break;
case t_NEGb:
case t_NEGw:
case t_NEGd:
*(Bit32u*)pos=0xd8f7c18b;
*(pos+4)=0x90;
break;
default:
*(Bit32u*)(pos+1)=(Bit32u)((Bit8u*)fct_ptr - (pos+1+4));
break;
}
#else
*(Bit32u*)(pos+1)=(Bit32u)((Bit8u*)fct_ptr - (pos+1+4));
#endif
}
#endif