From cccaf86fd33855607bea49a984d53de88ddad2d3 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 9 Sep 2020 21:49:28 +0100 Subject: [PATCH] Mark some exceptions (mainly v86 related) as 'expected', meaning they won't cause a code block deletion. This speeds up some v86 code due to a reduction in code block churning. --- src/386.c | 2 +- src/386_common.h | 5 ++++- src/386_dynarec.c | 13 ++++++++----- src/x86.h | 11 +++++++++++ src/x86_ops_int.h | 2 +- src/x86_ops_ret.h | 4 ++-- src/x86seg.c | 15 ++++++++++++--- 7 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/386.c b/src/386.c index 6b0dcd0..8276b40 100644 --- a/src/386.c +++ b/src/386.c @@ -196,7 +196,7 @@ void exec386(int cycs) flags_rebuild(); // pclog("Abort\n"); // if (CS == 0x228) pclog("Abort at %04X:%04X - %i %i %i\n",CS,pc,notpresent,nullseg,abrt); - tempi = cpu_state.abrt; + tempi = cpu_state.abrt & ABRT_MASK; cpu_state.abrt = 0; x86_doabrt(tempi); if (cpu_state.abrt) diff --git a/src/386_common.h b/src/386_common.h index 80da16d..143984a 100644 --- a/src/386_common.h +++ b/src/386_common.h @@ -19,7 +19,10 @@ int checkio(int port); if (cpu_state.abrt) return 1; \ if (tempi) \ { \ - x86gpf(NULL,0); \ + if (cpu_state.eflags & VM_FLAG) \ + x86gpf_expected(NULL,0); \ + else \ + x86gpf(NULL,0); \ return 1; \ } \ } diff --git a/src/386_dynarec.c b/src/386_dynarec.c index d52efde..171c6b3 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -462,7 +462,8 @@ static inline void exec_recompiler(void) if (cpu_state.abrt) { - codegen_block_remove(); + if (!(cpu_state.abrt & ABRT_EXPECTED)) + codegen_block_remove(); CPU_BLOCK_END(); } @@ -471,7 +472,7 @@ static inline void exec_recompiler(void) } cpu_end_block_after_ins = 0; - if (!cpu_state.abrt && !x86_was_reset) + if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !x86_was_reset) codegen_block_end_recompile(block); if (x86_was_reset) @@ -540,7 +541,8 @@ static inline void exec_recompiler(void) if (cpu_state.abrt) { - codegen_block_remove(); + if (!(cpu_state.abrt & ABRT_EXPECTED)) + codegen_block_remove(); CPU_BLOCK_END(); } @@ -549,7 +551,8 @@ static inline void exec_recompiler(void) } cpu_end_block_after_ins = 0; - if (!cpu_state.abrt && !x86_was_reset) +// if (!cpu_state.abrt && !x86_was_reset) + if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !x86_was_reset) codegen_block_end(); if (x86_was_reset) @@ -592,7 +595,7 @@ void exec386_dynarec(int cycs) if (cpu_state.abrt) { flags_rebuild(); - tempi = cpu_state.abrt; + tempi = cpu_state.abrt & ABRT_MASK; cpu_state.abrt = 0; x86_doabrt(tempi); if (cpu_state.abrt) diff --git a/src/x86.h b/src/x86.h index 753edf5..2665249 100644 --- a/src/x86.h +++ b/src/x86.h @@ -261,6 +261,16 @@ enum ABRT_PF = 0xE }; +#define ABRT_MASK 0x7f +/*An 'expected' exception is one that would be expected to occur on every execution + of this code path; eg a GPF due to being in v86 mode. An 'unexpected' exception is + one that would be unlikely to occur on the next exception, eg a page fault may be + fixed up by the exception handler and the next execution would not hit it. + + This distinction is used by the dynarec; a block that hits an 'expected' exception + would be compiled, a block that hits an 'unexpected' exception would be rejected so + that we don't end up with an unnecessarily short block*/ +#define ABRT_EXPECTED 0x80 extern uint32_t abrt_error; void x86_doabrt(int x86_abrt); @@ -275,6 +285,7 @@ void x86illegal(); void x86seg_reset(); void x86gpf(char *s, uint16_t error); +void x86gpf_expected(char *s, uint16_t error); void resetx86(); void softresetx86(); diff --git a/src/x86_ops_int.h b/src/x86_ops_int.h index efb2a5d..3ac96f3 100644 --- a/src/x86_ops_int.h +++ b/src/x86_ops_int.h @@ -59,7 +59,7 @@ static int opINT(uint32_t fetchdat) } } } - x86gpf(NULL,0); + x86gpf_expected(NULL,0); return 1; } // /*if (temp == 0x10 && AH == 0xe) */pclog("INT %02X : %04X %04X %04X %04X %c %04X:%04X\n", temp, AX, BX, CX, DX, (AL < 32) ? ' ' : AL, CS, pc); diff --git a/src/x86_ops_ret.h b/src/x86_ops_ret.h index 70ac327..3dd93f4 100644 --- a/src/x86_ops_ret.h +++ b/src/x86_ops_ret.h @@ -166,7 +166,7 @@ static int opIRET(uint32_t fetchdat) } else { - x86gpf(NULL,0); + x86gpf_expected(NULL,0); return 1; } } @@ -214,7 +214,7 @@ static int opIRETD(uint32_t fetchdat) if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { - x86gpf(NULL,0); + x86gpf_expected(NULL,0); return 1; } if (msw & 1) diff --git a/src/x86seg.c b/src/x86seg.c index f28e7c5..a69dfcd 100644 --- a/src/x86seg.c +++ b/src/x86seg.c @@ -161,10 +161,16 @@ void x86_doabrt(int x86_abrt) } void x86gpf(char *s, uint16_t error) { -// pclog("GPF %04X\n", error); +// pclog("GPF %04X %04x(%08x):%08x\n", error, CS,cs,cpu_state.pc); cpu_state.abrt = ABRT_GPF; abrt_error = error; } +void x86gpf_expected(char *s, uint16_t error) +{ +// pclog("GPF_v86 %04X %04x(%08x):%08x\n", error, CS,cs,cpu_state.pc); + cpu_state.abrt = ABRT_GPF | ABRT_EXPECTED; + abrt_error = error; +} void x86ss(char *s, uint16_t error) { // pclog("SS %04X\n", error); @@ -1715,8 +1721,11 @@ void pmodeint(int num, int soft) if (output) pclog("Addr %08X seg %04X %04X %04X %04X\n",addr,segdat[0],segdat[1],segdat[2],segdat[3]); if (!(segdat[2]&0x1F00)) { - //pclog("No seg\n"); - x86gpf(NULL,(num*8)+2); +// pclog("No seg\n"); + if (cpu_state.eflags & VM_FLAG) /*This fires on all V86 interrupts in EMM386. Mark as expected to prevent code churn*/ + x86gpf_expected(NULL,(num*8)+2); + else + x86gpf(NULL,(num*8)+2); return; } if (DPL