From 519554c8464ba8e8641e474bc949a2a0beae77ae Mon Sep 17 00:00:00 2001 From: cracyc Date: Sat, 4 Feb 2023 10:26:00 -0600 Subject: [PATCH] i386: nm fault if ts is set --- src/devices/cpu/i386/i386.cpp | 10 ++++++ src/devices/cpu/i386/i386ops.hxx | 5 +++ src/devices/cpu/i386/i486ops.hxx | 5 +++ src/devices/cpu/i386/pentops.hxx | 5 +++ src/devices/cpu/i386/x87ops.hxx | 57 +++++++++++++++++++++++++++++++- 5 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/devices/cpu/i386/i386.cpp b/src/devices/cpu/i386/i386.cpp index b15123bef15..4e1c653bec5 100644 --- a/src/devices/cpu/i386/i386.cpp +++ b/src/devices/cpu/i386/i386.cpp @@ -2017,6 +2017,16 @@ void i386_device::i386_common_init() save_item(NAME(m_nmi_latched)); save_item(NAME(m_smbase)); save_item(NAME(m_lock)); + + save_item(NAME(m_x87_cw)); + save_item(NAME(m_x87_tw)); + save_item(NAME(m_x87_sw)); + save_item(NAME(m_x87_cs)); + save_item(NAME(m_x87_ds)); + save_item(NAME(m_x87_inst_ptr)); + save_item(NAME(m_x87_data_ptr)); + save_item(NAME(m_x87_opcode)); + machine().save().register_postload(save_prepost_delegate(FUNC(i386_device::i386_postload), this)); m_smiact.resolve_safe(); diff --git a/src/devices/cpu/i386/i386ops.hxx b/src/devices/cpu/i386/i386ops.hxx index debd26ce224..1f15550a776 100644 --- a/src/devices/cpu/i386/i386ops.hxx +++ b/src/devices/cpu/i386/i386ops.hxx @@ -2491,6 +2491,11 @@ void i386_device::i386_clts() // Opcode 0x0f 0x06 void i386_device::i386_wait() // Opcode 0x9B { + if ((m_cr[0] & 0xa) == 0xa) + { + i386_trap(FAULT_NM, 0, 0); + return; + } // TODO } diff --git a/src/devices/cpu/i386/i486ops.hxx b/src/devices/cpu/i386/i486ops.hxx index 96eaaf21d08..2c7aeeda7c9 100644 --- a/src/devices/cpu/i386/i486ops.hxx +++ b/src/devices/cpu/i386/i486ops.hxx @@ -536,5 +536,10 @@ void i386_device::i486_mov_cr_r32() // Opcode 0x0f 22 void i386_device::i486_wait() { + if ((m_cr[0] & 0xa) == 0xa) + { + i386_trap(FAULT_NM, 0, 0); + return; + } x87_mf_fault(); } diff --git a/src/devices/cpu/i386/pentops.hxx b/src/devices/cpu/i386/pentops.hxx index 6822dcb7b15..2d8f046bc4d 100644 --- a/src/devices/cpu/i386/pentops.hxx +++ b/src/devices/cpu/i386/pentops.hxx @@ -7,6 +7,11 @@ extern flag float64_is_nan( float64 a ); // since its not defined in softfloat.h void i386_device::MMXPROLOG() { + if (m_cr[0] & 0xc) + { + i386_trap(FAULT_NM, 0, 0); + return; + } //m_x87_sw &= ~(X87_SW_TOP_MASK << X87_SW_TOP_SHIFT); // top = 0 m_x87_tw = 0; // tag word = 0 } diff --git a/src/devices/cpu/i386/x87ops.hxx b/src/devices/cpu/i386/x87ops.hxx index 1323f837bc2..c2bfeae0bcb 100644 --- a/src/devices/cpu/i386/x87ops.hxx +++ b/src/devices/cpu/i386/x87ops.hxx @@ -3164,7 +3164,10 @@ void i386_device::x87_fist_m16int(uint8_t modrm) if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) m16int = floatx80_to_int32(fx80); else + { + float_exception_flags = float_flag_invalid; m16int = -32768; + } } uint32_t ea = Getx87EA(modrm, 1); @@ -3199,7 +3202,10 @@ void i386_device::x87_fist_m32int(uint8_t modrm) if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) m32int = floatx80_to_int32(fx80); else + { + float_exception_flags = float_flag_invalid; m32int = 0x80000000; + } } uint32_t ea = Getx87EA(modrm, 1); @@ -3217,7 +3223,7 @@ void i386_device::x87_fistp_m16int(uint8_t modrm) if (x87_mf_fault()) return; -if (X87_IS_ST_EMPTY(0)) + if (X87_IS_ST_EMPTY(0)) { x87_set_stack_underflow(); m16int = (uint16_t)0x8000; @@ -3234,7 +3240,10 @@ if (X87_IS_ST_EMPTY(0)) if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) m16int = floatx80_to_int32(fx80); else + { + float_exception_flags = float_flag_invalid; m16int = (uint16_t)0x8000; + } } uint32_t ea = Getx87EA(modrm, 1); @@ -3270,7 +3279,10 @@ void i386_device::x87_fistp_m32int(uint8_t modrm) if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) m32int = floatx80_to_int32(fx80); else + { + float_exception_flags = float_flag_invalid; m32int = 0x80000000; + } } uint32_t ea = Getx87EA(modrm, 1); @@ -3306,7 +3318,10 @@ void i386_device::x87_fistp_m64int(uint8_t modrm) if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) m64int = floatx80_to_int64(fx80); else + { + float_exception_flags = float_flag_invalid; m64int = 0x8000000000000000U; + } } uint32_t ea = Getx87EA(modrm, 1); @@ -5055,48 +5070,88 @@ void i386_device::x87_invalid(uint8_t modrm) void i386_device::i386_x87_group_d8() { + if (m_cr[0] & 0xc) + { + i386_trap(FAULT_NM, 0, 0); + return; + } uint8_t modrm = FETCH(); (this->*m_opcode_table_x87_d8[modrm])(modrm); } void i386_device::i386_x87_group_d9() { + if (m_cr[0] & 0xc) + { + i386_trap(FAULT_NM, 0, 0); + return; + } uint8_t modrm = FETCH(); (this->*m_opcode_table_x87_d9[modrm])(modrm); } void i386_device::i386_x87_group_da() { + if (m_cr[0] & 0xc) + { + i386_trap(FAULT_NM, 0, 0); + return; + } uint8_t modrm = FETCH(); (this->*m_opcode_table_x87_da[modrm])(modrm); } void i386_device::i386_x87_group_db() { + if (m_cr[0] & 0xc) + { + i386_trap(FAULT_NM, 0, 0); + return; + } uint8_t modrm = FETCH(); (this->*m_opcode_table_x87_db[modrm])(modrm); } void i386_device::i386_x87_group_dc() { + if (m_cr[0] & 0xc) + { + i386_trap(FAULT_NM, 0, 0); + return; + } uint8_t modrm = FETCH(); (this->*m_opcode_table_x87_dc[modrm])(modrm); } void i386_device::i386_x87_group_dd() { + if (m_cr[0] & 0xc) + { + i386_trap(FAULT_NM, 0, 0); + return; + } uint8_t modrm = FETCH(); (this->*m_opcode_table_x87_dd[modrm])(modrm); } void i386_device::i386_x87_group_de() { + if (m_cr[0] & 0xc) + { + i386_trap(FAULT_NM, 0, 0); + return; + } uint8_t modrm = FETCH(); (this->*m_opcode_table_x87_de[modrm])(modrm); } void i386_device::i386_x87_group_df() { + if (m_cr[0] & 0xc) + { + i386_trap(FAULT_NM, 0, 0); + return; + } uint8_t modrm = FETCH(); (this->*m_opcode_table_x87_df[modrm])(modrm); }