i386: don't change x87 stack pointer until after memory access in case of a page fault

This commit is contained in:
cracyc 2023-01-23 21:10:36 -06:00
parent 0b67aa20c7
commit 45e3f79a90
3 changed files with 79 additions and 16 deletions

View File

@ -2133,14 +2133,14 @@ void i386_device::register_state_i386_x87()
state_add( X87_CTRL, "x87_CW", m_x87_cw).formatstr("%04X");
state_add( X87_STATUS, "x87_SW", m_x87_sw).formatstr("%04X");
state_add( X87_TAG, "x87_TAG", m_x87_tw).formatstr("%04X");
state_add( X87_ST0, "ST0", m_debugger_temp ).formatstr("%15s");
state_add( X87_ST1, "ST1", m_debugger_temp ).formatstr("%15s");
state_add( X87_ST2, "ST2", m_debugger_temp ).formatstr("%15s");
state_add( X87_ST3, "ST3", m_debugger_temp ).formatstr("%15s");
state_add( X87_ST4, "ST4", m_debugger_temp ).formatstr("%15s");
state_add( X87_ST5, "ST5", m_debugger_temp ).formatstr("%15s");
state_add( X87_ST6, "ST6", m_debugger_temp ).formatstr("%15s");
state_add( X87_ST7, "ST7", m_debugger_temp ).formatstr("%15s");
state_add( X87_ST0, "ST0", m_debugger_temp ).callexport().formatstr("%15s");
state_add( X87_ST1, "ST1", m_debugger_temp ).callexport().formatstr("%15s");
state_add( X87_ST2, "ST2", m_debugger_temp ).callexport().formatstr("%15s");
state_add( X87_ST3, "ST3", m_debugger_temp ).callexport().formatstr("%15s");
state_add( X87_ST4, "ST4", m_debugger_temp ).callexport().formatstr("%15s");
state_add( X87_ST5, "ST5", m_debugger_temp ).callexport().formatstr("%15s");
state_add( X87_ST6, "ST6", m_debugger_temp ).callexport().formatstr("%15s");
state_add( X87_ST7, "ST7", m_debugger_temp ).callexport().formatstr("%15s");
}
void i386_device::register_state_i386_x87_xmm()
@ -2197,6 +2197,30 @@ void i386_device::state_export(const device_state_entry &entry)
case I386_IP:
m_debugger_temp = m_eip & 0xffff;
break;
case X87_ST0:
m_debugger_temp = floatx80_to_float64(ST(0));
break;
case X87_ST1:
m_debugger_temp = floatx80_to_float64(ST(1));
break;
case X87_ST2:
m_debugger_temp = floatx80_to_float64(ST(2));
break;
case X87_ST3:
m_debugger_temp = floatx80_to_float64(ST(3));
break;
case X87_ST4:
m_debugger_temp = floatx80_to_float64(ST(4));
break;
case X87_ST5:
m_debugger_temp = floatx80_to_float64(ST(5));
break;
case X87_ST6:
m_debugger_temp = floatx80_to_float64(ST(6));
break;
case X87_ST7:
m_debugger_temp = floatx80_to_float64(ST(7));
break;
}
}

View File

@ -1359,6 +1359,7 @@ protected:
inline void x87_set_stack_overflow();
int x87_inc_stack();
int x87_dec_stack();
int x87_ck_over_stack();
int x87_check_exceptions(bool store = false);
int x87_mf_fault();
inline void x87_write_cw(uint16_t cw);

View File

@ -117,6 +117,23 @@ int i386_device::x87_dec_stack()
return ret;
}
int i386_device::x87_ck_over_stack()
{
int ret = 1;
// Check for stack overflow
if (!X87_IS_ST_EMPTY(7))
{
ret = 0;
x87_set_stack_overflow();
// Don't update the stack if the exception is unmasked
if (~m_x87_cw & X87_CW_IM)
return ret;
}
return ret;
}
/*************************************
*
@ -145,7 +162,7 @@ uint32_t i386_device::Getx87EA(uint8_t modrm, int rwn)
if (PROTECTED_MODE && !V8086_MODE)
m_x87_data_ptr = ea;
else
m_x87_data_ptr = ea + (segment << 4);
m_x87_data_ptr = ea + (m_x87_ds << 4);
m_x87_opcode = ((m_opcode << 8) | modrm) & 0x7ff;
return ret;
}
@ -2685,7 +2702,7 @@ void i386_device::x87_fld_m32real(uint8_t modrm)
if (x87_mf_fault())
return;
uint32_t ea = Getx87EA(modrm, 0);
if (x87_dec_stack())
if (x87_ck_over_stack())
{
uint32_t m32real = READ32(ea);
@ -2705,7 +2722,10 @@ void i386_device::x87_fld_m32real(uint8_t modrm)
}
if (x87_check_exceptions())
{
x87_set_stack_top(ST_TO_PHYS(7));
x87_write_stack(0, value, true);
}
CYCLES(3);
}
@ -2717,7 +2737,7 @@ void i386_device::x87_fld_m64real(uint8_t modrm)
if (x87_mf_fault())
return;
uint32_t ea = Getx87EA(modrm, 0);
if (x87_dec_stack())
if (x87_ck_over_stack())
{
uint64_t m64real = READ64(ea);
@ -2737,7 +2757,10 @@ void i386_device::x87_fld_m64real(uint8_t modrm)
}
if (x87_check_exceptions())
{
x87_set_stack_top(ST_TO_PHYS(7));
x87_write_stack(0, value, true);
}
CYCLES(3);
}
@ -2749,7 +2772,7 @@ void i386_device::x87_fld_m80real(uint8_t modrm)
if (x87_mf_fault())
return;
uint32_t ea = Getx87EA(modrm, 0);
if (x87_dec_stack())
if (x87_ck_over_stack())
{
m_x87_sw &= ~X87_SW_C1;
value = READ80(ea);
@ -2760,7 +2783,10 @@ void i386_device::x87_fld_m80real(uint8_t modrm)
}
if (x87_check_exceptions())
{
x87_set_stack_top(ST_TO_PHYS(7));
x87_write_stack(0, value, true);
}
CYCLES(6);
}
@ -2797,7 +2823,7 @@ void i386_device::x87_fild_m16int(uint8_t modrm)
if (x87_mf_fault())
return;
uint32_t ea = Getx87EA(modrm, 0);
if (!x87_dec_stack())
if (!x87_ck_over_stack())
{
value = fx80_inan;
}
@ -2810,7 +2836,10 @@ void i386_device::x87_fild_m16int(uint8_t modrm)
}
if (x87_check_exceptions())
{
x87_set_stack_top(ST_TO_PHYS(7));
x87_write_stack(0, value, true);
}
CYCLES(13);
}
@ -2822,7 +2851,7 @@ void i386_device::x87_fild_m32int(uint8_t modrm)
if (x87_mf_fault())
return;
uint32_t ea = Getx87EA(modrm, 0);
if (!x87_dec_stack())
if (!x87_ck_over_stack())
{
value = fx80_inan;
}
@ -2835,7 +2864,10 @@ void i386_device::x87_fild_m32int(uint8_t modrm)
}
if (x87_check_exceptions())
{
x87_set_stack_top(ST_TO_PHYS(7));
x87_write_stack(0, value, true);
}
CYCLES(9);
}
@ -2847,7 +2879,7 @@ void i386_device::x87_fild_m64int(uint8_t modrm)
if (x87_mf_fault())
return;
uint32_t ea = Getx87EA(modrm, 0);
if (!x87_dec_stack())
if (!x87_ck_over_stack())
{
value = fx80_inan;
}
@ -2860,7 +2892,10 @@ void i386_device::x87_fild_m64int(uint8_t modrm)
}
if (x87_check_exceptions())
{
x87_set_stack_top(ST_TO_PHYS(7));
x87_write_stack(0, value, true);
}
CYCLES(10);
}
@ -2872,7 +2907,7 @@ void i386_device::x87_fbld(uint8_t modrm)
if (x87_mf_fault())
return;
uint32_t ea = Getx87EA(modrm, 0);
if (!x87_dec_stack())
if (!x87_ck_over_stack())
{
value = fx80_inan;
}
@ -2900,7 +2935,10 @@ void i386_device::x87_fbld(uint8_t modrm)
}
if (x87_check_exceptions())
{
x87_set_stack_top(ST_TO_PHYS(7));
x87_write_stack(0, value, true);
}
CYCLES(75);
}