From 45e3f79a902c31b20224146e1d7bd881a064115e Mon Sep 17 00:00:00 2001 From: cracyc Date: Mon, 23 Jan 2023 21:10:36 -0600 Subject: i386: don't change x87 stack pointer until after memory access in case of a page fault --- src/devices/cpu/i386/i386.cpp | 40 ++++++++++++++++++++++++------ src/devices/cpu/i386/i386.h | 1 + src/devices/cpu/i386/x87ops.hxx | 54 +++++++++++++++++++++++++++++++++++------ 3 files changed, 79 insertions(+), 16 deletions(-) diff --git a/src/devices/cpu/i386/i386.cpp b/src/devices/cpu/i386/i386.cpp index 152691db3c3..b15123bef15 100644 --- a/src/devices/cpu/i386/i386.cpp +++ b/src/devices/cpu/i386/i386.cpp @@ -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; } } diff --git a/src/devices/cpu/i386/i386.h b/src/devices/cpu/i386/i386.h index 6fd5785a9a4..5d313847242 100644 --- a/src/devices/cpu/i386/i386.h +++ b/src/devices/cpu/i386/i386.h @@ -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); diff --git a/src/devices/cpu/i386/x87ops.hxx b/src/devices/cpu/i386/x87ops.hxx index c968f65a2b0..1323f837bc2 100644 --- a/src/devices/cpu/i386/x87ops.hxx +++ b/src/devices/cpu/i386/x87ops.hxx @@ -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); } -- cgit v1.2.3