summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author cracyc <cracyc@users.noreply.github.com>2023-02-11 19:26:01 -0600
committer cracyc <cracyc@users.noreply.github.com>2023-02-11 19:26:01 -0600
commit397cc6b217babb7ed50b4567d28cf387bcb51cf8 (patch)
tree217957a22f01e8c9dcb1cafd258ede2acdc74175 /src
parent0ad3bf7c040c528cc8ebea73eab8810f1fc630ca (diff)
i386: add fxsave and fxstor
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/i386/pentops.hxx66
1 files changed, 65 insertions, 1 deletions
diff --git a/src/devices/cpu/i386/pentops.hxx b/src/devices/cpu/i386/pentops.hxx
index a43ecf30161..4d5b4a88a7e 100644
--- a/src/devices/cpu/i386/pentops.hxx
+++ b/src/devices/cpu/i386/pentops.hxx
@@ -2801,12 +2801,76 @@ void i386_device::sse_group_0fae() // Opcode 0f ae
uint32_t ea;
switch ( (modm & 0x38) >> 3 )
{
+ case 0: // fxsave
+ {
+ u8 atag = 0;
+ ea = GetEA(modm, 1);
+ WRITE16(ea + 0, m_x87_cw);
+ WRITE16(ea + 2, m_x87_sw);
+ for(int i = 0; i < 8; i++)
+ if((m_x87_tw & (3 << i)) != 3) atag |= 1 << i;
+ WRITE16(ea + 4, atag);
+ WRITE16(ea + 6, m_x87_opcode);
+ WRITE32(ea + 8, m_x87_inst_ptr);
+ WRITE32(ea + 12, m_x87_cs);
+ WRITE32(ea + 16, m_x87_data_ptr);
+ WRITE32(ea + 20, m_x87_ds);
+ WRITE32(ea + 24, m_mxcsr);
+ WRITE32(ea + 28, 0); // mxcsr_mask
+ for(int i = 0; i < 8; i++)
+ {
+ WRITE64(ea + i*16 + 32, m_x87_reg[i].low);
+ WRITE64(ea + i*16 + 40, m_x87_reg[i].high);
+ }
+ for(int i = 0; i < 8; i++)
+ {
+ WRITE64(ea + i*16 + 160, m_sse_reg[i].q[0]);
+ WRITE64(ea + i*16 + 168, m_sse_reg[i].q[1]);
+ }
+ break;
+ }
+ case 1:
+ {
+ u8 atag;
+ ea = GetEA(modm, 0);
+ x87_write_cw(READ16(ea));
+ m_x87_sw = READ16(ea + 2);
+ atag = READ8(ea + 4);
+ m_x87_opcode = READ16(ea + 6);
+ m_x87_inst_ptr = READ32(ea + 8);
+ m_x87_cs = READ16(ea + 12);
+ m_x87_data_ptr = READ32(ea + 16);
+ m_x87_ds = READ16(ea + 20);
+ m_mxcsr = READ32(ea + 24);
+ // mxcsr_mask
+ for(int i = 0; i < 8; i++)
+ {
+ int tag;
+ m_x87_reg[i].low = READ64(ea + i*16 + 32);
+ m_x87_reg[i].high = READ16(ea + i*16 + 40);
+ if(!(atag & (1 << i)))
+ tag = X87_TW_EMPTY;
+ if(floatx80_is_zero(m_x87_reg[i]))
+ tag = X87_TW_ZERO;
+ else if(floatx80_is_inf(m_x87_reg[i]) || floatx80_is_nan(m_x87_reg[i]))
+ tag = X87_TW_SPECIAL;
+ else
+ tag = X87_TW_VALID;
+ x87_set_tag(i, tag);
+ }
+ for(int i = 0; i < 8; i++)
+ {
+ m_sse_reg[i].q[0] = READ64(ea + i*16 + 160);
+ m_sse_reg[i].q[1] = READ64(ea + i*16 + 168);
+ }
+ break;
+ }
case 2: // ldmxcsr m32
ea = GetEA(modm, 0);
m_mxcsr = READ32(ea);
break;
case 3: // stmxcsr m32
- ea = GetEA(modm, 0);
+ ea = GetEA(modm, 1);
WRITE32(ea, m_mxcsr);
break;
case 7: // clflush m8