From 4fe71bdbed6ea85fd636d4e0b509de031634a7ff Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 1 Jul 2020 21:50:11 +0100 Subject: [PATCH] The instruction following STI is always executed, even if an interrupt is pending. Fixes Windows 9x boot broken by SYSENTER commit. --- src/386_dynarec.c | 25 +++++++++++++++++++++++++ src/x86.h | 2 ++ src/x86_ops_flag.h | 9 +++++---- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/386_dynarec.c b/src/386_dynarec.c index fd2861b..12ecebf 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -238,6 +238,8 @@ static void prefetch_flush() #define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG)) //#define CACHE_ON() 0 +int cpu_end_block_after_ins = 0; + static int cycles_main = 0; void exec386_dynarec(int cycs) { @@ -297,10 +299,17 @@ void exec386_dynarec(int cycs) CPU_BLOCK_END(); if (nmi && nmi_enable && nmi_mask) CPU_BLOCK_END(); + if (cpu_end_block_after_ins) + { + cpu_end_block_after_ins--; + if (!cpu_end_block_after_ins) + CPU_BLOCK_END(); + } ins++; insc++; } + cpu_end_block_after_ins = 0; } else { @@ -458,6 +467,13 @@ void exec386_dynarec(int cycs) if (nmi && nmi_enable && nmi_mask) CPU_BLOCK_END(); + if (cpu_end_block_after_ins) + { + cpu_end_block_after_ins--; + if (!cpu_end_block_after_ins) + CPU_BLOCK_END(); + } + if (cpu_state.abrt) { codegen_block_remove(); @@ -467,6 +483,7 @@ void exec386_dynarec(int cycs) ins++; insc++; } + cpu_end_block_after_ins = 0; if (!cpu_state.abrt && !x86_was_reset) codegen_block_end_recompile(block); @@ -530,6 +547,13 @@ void exec386_dynarec(int cycs) if (nmi && nmi_enable && nmi_mask) CPU_BLOCK_END(); + if (cpu_end_block_after_ins) + { + cpu_end_block_after_ins--; + if (!cpu_end_block_after_ins) + CPU_BLOCK_END(); + } + if (cpu_state.abrt) { codegen_block_remove(); @@ -539,6 +563,7 @@ void exec386_dynarec(int cycs) ins++; insc++; } + cpu_end_block_after_ins = 0; if (!cpu_state.abrt && !x86_was_reset) codegen_block_end(); diff --git a/src/x86.h b/src/x86.h index 578ebdd..753edf5 100644 --- a/src/x86.h +++ b/src/x86.h @@ -303,4 +303,6 @@ void sysexit(void); int divl(uint32_t val); int idivl(int32_t val); +extern int cpu_end_block_after_ins; + #endif diff --git a/src/x86_ops_flag.h b/src/x86_ops_flag.h index 04ceda1..64f43e9 100644 --- a/src/x86_ops_flag.h +++ b/src/x86_ops_flag.h @@ -85,12 +85,13 @@ static int opSTI(uint32_t fetchdat) else cpu_state.flags |= I_FLAG; -/*TODO - should end block after 1 further instruction*/ -// CPU_BLOCK_END(); - + /*First instruction after STI will always execute, regardless of whether + there is a pending interrupt*/ + cpu_end_block_after_ins = 2; + CLOCK_CYCLES(2); PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); - return 1; + return 0; } static int opSAHF(uint32_t fetchdat)