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:
parent
2773ef7adf
commit
60292aed8b
6 changed files with 161 additions and 72 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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*/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue