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.
This commit is contained in:
SarahW 2020-09-09 21:49:28 +01:00
commit cccaf86fd3
7 changed files with 39 additions and 13 deletions

View file

@ -196,7 +196,7 @@ void exec386(int cycs)
flags_rebuild(); flags_rebuild();
// pclog("Abort\n"); // pclog("Abort\n");
// if (CS == 0x228) pclog("Abort at %04X:%04X - %i %i %i\n",CS,pc,notpresent,nullseg,abrt); // 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; cpu_state.abrt = 0;
x86_doabrt(tempi); x86_doabrt(tempi);
if (cpu_state.abrt) if (cpu_state.abrt)

View file

@ -19,7 +19,10 @@ int checkio(int port);
if (cpu_state.abrt) return 1; \ if (cpu_state.abrt) return 1; \
if (tempi) \ if (tempi) \
{ \ { \
x86gpf(NULL,0); \ if (cpu_state.eflags & VM_FLAG) \
x86gpf_expected(NULL,0); \
else \
x86gpf(NULL,0); \
return 1; \ return 1; \
} \ } \
} }

View file

@ -462,7 +462,8 @@ static inline void exec_recompiler(void)
if (cpu_state.abrt) if (cpu_state.abrt)
{ {
codegen_block_remove(); if (!(cpu_state.abrt & ABRT_EXPECTED))
codegen_block_remove();
CPU_BLOCK_END(); CPU_BLOCK_END();
} }
@ -471,7 +472,7 @@ static inline void exec_recompiler(void)
} }
cpu_end_block_after_ins = 0; 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); codegen_block_end_recompile(block);
if (x86_was_reset) if (x86_was_reset)
@ -540,7 +541,8 @@ static inline void exec_recompiler(void)
if (cpu_state.abrt) if (cpu_state.abrt)
{ {
codegen_block_remove(); if (!(cpu_state.abrt & ABRT_EXPECTED))
codegen_block_remove();
CPU_BLOCK_END(); CPU_BLOCK_END();
} }
@ -549,7 +551,8 @@ static inline void exec_recompiler(void)
} }
cpu_end_block_after_ins = 0; 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(); codegen_block_end();
if (x86_was_reset) if (x86_was_reset)
@ -592,7 +595,7 @@ void exec386_dynarec(int cycs)
if (cpu_state.abrt) if (cpu_state.abrt)
{ {
flags_rebuild(); flags_rebuild();
tempi = cpu_state.abrt; tempi = cpu_state.abrt & ABRT_MASK;
cpu_state.abrt = 0; cpu_state.abrt = 0;
x86_doabrt(tempi); x86_doabrt(tempi);
if (cpu_state.abrt) if (cpu_state.abrt)

View file

@ -261,6 +261,16 @@ enum
ABRT_PF = 0xE 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; extern uint32_t abrt_error;
void x86_doabrt(int x86_abrt); void x86_doabrt(int x86_abrt);
@ -275,6 +285,7 @@ void x86illegal();
void x86seg_reset(); void x86seg_reset();
void x86gpf(char *s, uint16_t error); void x86gpf(char *s, uint16_t error);
void x86gpf_expected(char *s, uint16_t error);
void resetx86(); void resetx86();
void softresetx86(); void softresetx86();

View file

@ -59,7 +59,7 @@ static int opINT(uint32_t fetchdat)
} }
} }
} }
x86gpf(NULL,0); x86gpf_expected(NULL,0);
return 1; 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); // /*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);

View file

@ -166,7 +166,7 @@ static int opIRET(uint32_t fetchdat)
} }
else else
{ {
x86gpf(NULL,0); x86gpf_expected(NULL,0);
return 1; return 1;
} }
} }
@ -214,7 +214,7 @@ static int opIRETD(uint32_t fetchdat)
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3))
{ {
x86gpf(NULL,0); x86gpf_expected(NULL,0);
return 1; return 1;
} }
if (msw & 1) if (msw & 1)

View file

@ -161,10 +161,16 @@ void x86_doabrt(int x86_abrt)
} }
void x86gpf(char *s, uint16_t error) 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; cpu_state.abrt = ABRT_GPF;
abrt_error = error; 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) void x86ss(char *s, uint16_t error)
{ {
// pclog("SS %04X\n", 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 (output) pclog("Addr %08X seg %04X %04X %04X %04X\n",addr,segdat[0],segdat[1],segdat[2],segdat[3]);
if (!(segdat[2]&0x1F00)) if (!(segdat[2]&0x1F00))
{ {
//pclog("No seg\n"); // pclog("No seg\n");
x86gpf(NULL,(num*8)+2); 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; return;
} }
if (DPL<CPL && soft) if (DPL<CPL && soft)