Merge pull request #2169 from koolkdev/dynamic-core-trap-flag

Handle trap flag after POPF in dynamic cores
This commit is contained in:
Jonathan Campbell
2021-01-07 17:11:38 -08:00
committed by GitHub
5 changed files with 77 additions and 4 deletions

View File

@@ -119,7 +119,8 @@ enum BlockReturn {
#endif
BR_Iret,
BR_CallBack,
BR_SMCBlock
BR_SMCBlock,
BR_Trap
};
#define SMC_CURRENT_BLOCK 0xffff
@@ -378,6 +379,17 @@ run_block:
}
}
goto restart_core;
case BR_Trap:
// trapflag is set, switch to the trap-aware decoder
#if C_DEBUG
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) {
return debugCallback;
}
#endif
#endif
cpudecoder=CPU_Core_Dyn_X86_Trap_Run;
return CBRET_NONE;
}
return CBRET_NONE;
}

View File

@@ -312,7 +312,7 @@ static INLINE void dyn_set_eip_last(void) {
}
enum save_info_type {db_exception, cycle_check, normal, fpu_restore};
enum save_info_type {db_exception, cycle_check, normal, fpu_restore, trap};
static struct {
@@ -376,6 +376,18 @@ static void dyn_check_irqrequest(void) {
used_save_info++;
}
static void dyn_check_trapflag(void) {
gen_dop_word_imm(DOP_TEST,true,DREG(FLAGS),FLAG_TF);
save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ);
gen_releasereg(DREG(FLAGS));
dyn_savestate(&save_info[used_save_info].state);
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=trap;
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);
@@ -408,6 +420,14 @@ static void dyn_fill_blocks(void) {
dyn_save_critical_regs();
gen_return(BR_Cycles);
break;
case trap:
dyn_loadstate(&save_info[sct].state);
decode.cycles=save_info[sct].cycles;
dyn_reduce_cycles();
gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),save_info[sct].eip_change);
dyn_save_critical_regs();
gen_return(BR_Trap);
break;
#ifdef X86_DYNFPU_DH_ENABLED
case fpu_restore:
dyn_loadstate(&save_info[sct].state);
@@ -2456,6 +2476,7 @@ restart_prefix:
dyn_flags_host_to_gen();
gen_releasereg(DREG(TMPB));
dyn_check_irqrequest();
dyn_check_trapflag();
break;
/* MOV AL,direct addresses */
case 0xa0:

View File

@@ -91,6 +91,8 @@
// access to a general register
#define DRCD_REG_VAL(reg) (&cpu_regs.regs[reg].dword)
// access to the flags register
#define DRCD_REG_FLAGS (&cpu_regs.flags)
// access to a segment register
#define DRCD_SEG_VAL(seg) (&Segs.val[seg])
// access to the physical value of a segment register/selector
@@ -112,7 +114,8 @@ enum BlockReturn {
#endif
BR_Iret,
BR_CallBack,
BR_SMCBlock
BR_SMCBlock,
BR_Trap
};
// identificator to signal self-modification of the currently executed block
@@ -381,6 +384,18 @@ run_block:
if (block) goto run_block;
break;
case BR_Trap:
// trapflag is set, switch to the trap-aware decoder
#if C_DEBUG
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) {
return debugCallback;
}
#endif
#endif
cpudecoder=CPU_Core_Dynrec_Trap_Run;
return CBRET_NONE;
default:
E_Exit("Invalid return code %d", ret);
}

View File

@@ -361,6 +361,7 @@ restart_prefix:
case 0x9d: // popf
gen_call_function_I(CPU_POPF,decode.big_op);
dyn_check_exception(FC_RETOP);
dyn_check_trapflag();
InvalidateFlags();
break;

View File

@@ -426,6 +426,8 @@ static void INLINE dyn_get_modrm(void) {
#define MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(host_reg, reg_index, high_byte) gen_mov_regbyte_to_reg_low_canuseword(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_BYTE(reg_index,high_byte)) - (DRC_PTR_SIZE_IM)(&cpu_regs))
#define MOV_REG_BYTE_FROM_HOST_REG_LOW(host_reg, reg_index, high_byte) gen_mov_regbyte_from_reg_low(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_BYTE(reg_index,high_byte)) - (DRC_PTR_SIZE_IM)(&cpu_regs))
#define MOV_FLAGS_TO_HOST_REG(host_reg) gen_mov_regval32_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_FLAGS) - (DRC_PTR_SIZE_IM)(&cpu_regs))
#else
#define MOV_REG_VAL_TO_HOST_REG(host_reg, reg_index) gen_mov_word_to_reg(host_reg,DRCD_REG_VAL(reg_index),true)
@@ -443,6 +445,8 @@ static void INLINE dyn_get_modrm(void) {
#define MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(host_reg, reg_index, high_byte) gen_mov_byte_to_reg_low_canuseword(host_reg,DRCD_REG_BYTE(reg_index,high_byte))
#define MOV_REG_BYTE_FROM_HOST_REG_LOW(host_reg, reg_index, high_byte) gen_mov_byte_from_reg_low(host_reg,DRCD_REG_BYTE(reg_index,high_byte))
#define MOV_FLAGS_TO_HOST_REG(host_reg) gen_mov_word_to_reg(host_reg,DRCD_REG_FLAGS,true)
#endif
@@ -610,7 +614,7 @@ template <typename T> static DRC_PTR_SIZE_IM INLINE gen_call_function_mm(const T
enum save_info_type {db_exception, cycle_check, string_break};
enum save_info_type {db_exception, cycle_check, string_break, trap};
// function that is called on exceptions
@@ -670,6 +674,13 @@ static void dyn_fill_blocks(void) {
gen_add_direct_word(&reg_eip,save_info_dynrec[sct].eip_change,decode.big_op);
dyn_return(BR_Cycles);
break;
case trap:
// trapflag is set, switch to trap-aware decoder
decode.cycles=save_info_dynrec[sct].cycles;
dyn_reduce_cycles();
gen_add_direct_word(&reg_eip,save_info_dynrec[sct].eip_change,decode.big_op);
dyn_return(BR_Trap);
break;
}
}
used_save_info_dynrec=0;
@@ -698,6 +709,19 @@ static void dyn_check_exception(HostReg reg) {
}
// check and branch if the trap flag is turned on
static void dyn_check_trapflag(void) {
MOV_FLAGS_TO_HOST_REG(FC_OP1);
gen_and_imm(FC_OP1, FLAG_TF);
save_info_dynrec[used_save_info_dynrec].branch_pos=gen_create_branch_long_nonzero(FC_OP1,true);
save_info_dynrec[used_save_info_dynrec].cycles=decode.cycles;
save_info_dynrec[used_save_info_dynrec].eip_change=decode.code-decode.code_start;
if (!cpu.code.big) save_info_dynrec[used_save_info_dynrec].eip_change&=0xffff;
save_info_dynrec[used_save_info_dynrec].type=trap;
used_save_info_dynrec++;
}
bool DRC_CALL_CONV mem_readb_checked_drc(PhysPt address) DRC_FC;
bool DRC_CALL_CONV mem_readb_checked_drc(PhysPt address) {