FPU: Properly implement INT 10h FPU exception, fixes #5162.

This commit is contained in:
OBattler 2025-01-19 09:06:39 +01:00
parent 5e12d46f32
commit 40fd79aeb9
10 changed files with 55 additions and 15 deletions

View file

@ -268,7 +268,8 @@ exec386_2386(int32_t cycs)
} else {
CHECK_READ_CS(MIN(ol, 4));
}
ins_fetch_fault = cpu_386_check_instruction_fault();
if (is386)
ins_fetch_fault = cpu_386_check_instruction_fault();
/* Breakpoint fault has priority over other faults. */
if (ins_fetch_fault) {
@ -336,6 +337,14 @@ exec386_2386(int32_t cycs)
#endif
}
}
} else if (new_ne) {
flags_rebuild();
new_ne = 0;
#ifndef USE_NEW_DYNAREC
oldcs = CS;
#endif
cpu_state.oldpc = cpu_state.pc;
x86_int(16);
} else if (trap) {
flags_rebuild();
if (trap & 2) dr[6] |= 0x8000;

View file

@ -72,6 +72,7 @@ extern uint8_t *pccache2;
extern int optype;
extern uint32_t pccache;
int new_ne = 0;
int in_sys = 0;
int unmask_a20_in_smm = 0;
uint32_t old_rammask = 0xffffffff;

View file

@ -357,6 +357,8 @@ exec386_dynarec_int(void)
CPU_BLOCK_END();
if (smi_line)
CPU_BLOCK_END();
else if (new_ne)
CPU_BLOCK_END();
else if (trap)
CPU_BLOCK_END();
else if (nmi && nmi_enable && nmi_mask)
@ -366,7 +368,7 @@ exec386_dynarec_int(void)
}
block_ended:
if (!cpu_state.abrt && trap) {
if (!cpu_state.abrt && !new_ne && trap) {
# ifdef USE_DEBUG_REGS_486
//pclog("Debug trap 0x%X\n", trap);
if (trap & 2) dr[6] |= 0x8000;
@ -602,6 +604,8 @@ exec386_dynarec_dyn(void)
if (cpu_init)
CPU_BLOCK_END();
if (new_ne)
CPU_BLOCK_END();
if ((cpu_state.flags & T_FLAG) || (trap == 2))
CPU_BLOCK_END();
if (smi_line)
@ -626,7 +630,7 @@ exec386_dynarec_dyn(void)
cpu_end_block_after_ins = 0;
if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !x86_was_reset)
if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !new_ne && !x86_was_reset)
codegen_block_end_recompile(block);
if (x86_was_reset)
@ -702,6 +706,8 @@ exec386_dynarec_dyn(void)
if (cpu_init)
CPU_BLOCK_END();
if (new_ne)
CPU_BLOCK_END();
if (cpu_state.flags & T_FLAG)
CPU_BLOCK_END();
if (smi_line)
@ -726,7 +732,7 @@ exec386_dynarec_dyn(void)
cpu_end_block_after_ins = 0;
if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !x86_was_reset)
if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !new_ne && !x86_was_reset)
codegen_block_end();
if (x86_was_reset)
@ -809,6 +815,15 @@ exec386_dynarec(int32_t cycs)
}
}
if (new_ne) {
# ifndef USE_NEW_DYNAREC
oldcs = CS;
# endif
cpu_state.oldpc = cpu_state.pc;
new_ne = 0;
x86_int(16);
}
if (smi_line)
enter_smm_check(0);
else if (nmi && nmi_enable && nmi_mask) {
@ -977,6 +992,15 @@ block_ended:
#endif
}
}
} else if (new_ne) {
flags_rebuild();
new_ne = 0;
#ifndef USE_NEW_DYNAREC
oldcs = CS;
#endif
cpu_state.oldpc = cpu_state.pc;
x86_int(16);
} else if (trap) {
flags_rebuild();
#ifdef USE_DEBUG_REGS_486

View file

@ -814,6 +814,8 @@ extern int lock_legal_80[8];
extern int lock_legal_f6[8];
extern int lock_legal_fe[8];
extern int new_ne;
extern int in_lock;
extern int cpu_override_interpreter;

View file

@ -271,6 +271,7 @@ reset_common(int hard)
stack32 = 0;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
msw = 0;
new_ne = 0;
if (hascache)
cr0 = 1 << 30;
else

View file

@ -99,8 +99,8 @@ opWAIT(uint32_t fetchdat)
if (fpu_softfloat) {
if (fpu_state.swd & FPU_SW_Summary) {
if (is486 && (cr0 & 0x20))
x86_int(16);
if (cr0 & 0x20)
new_ne = 1;
else
picint(1 << 13);
return 1;

View file

@ -99,7 +99,10 @@ opWAIT(uint32_t fetchdat)
if (fpu_softfloat) {
if (fpu_state.swd & FPU_SW_Summary) {
picint(1 << 13);
if (cr0 & 0x20)
new_ne = 1;
else
picint(1 << 13);
return 1;
}
}

View file

@ -355,10 +355,10 @@ FPU_exception(uint32_t fetchdat, uint16_t exceptions, int store)
nmi = 1;
}
#else
if (is486 && (cr0 & 0x20))
x86_int(16);
else
picint(1 << 13);
if (cr0 & 0x20)
new_ne = 1;
else
picint(1 << 13);
#endif // FPU_8087
}
return unmasked;

View file

@ -228,8 +228,8 @@ FPU_save_regi_tag(extFloat80_t reg, int tag, int stnr)
#define FPU_check_pending_exceptions() \
do { \
if (fpu_state.swd & FPU_SW_Summary) { \
if (is486 && (cr0 & 0x20)) \
x86_int(16); \
if (cr0 & 0x20) \
new_ne = 1; \
else \
picint(1 << 13); \
return 1; \

View file

@ -99,8 +99,8 @@ typedef union {
dst = src1 / (double) src2; \
else { \
fpu_log("FPU : divide by zero\n"); \
if (is486 && (cr0 & 0x20)) \
x86_int(16); \
if (cr0 & 0x20) \
new_ne = 1; \
else \
picint(1 << 13); \
return 1; \