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();
// 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)

View file

@ -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; \
} \
}

View file

@ -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)

View file

@ -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();

View file

@ -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);

View file

@ -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)

View file

@ -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<CPL && soft)