summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Olivier Galibert <galibert@pobox.com>2014-11-09 20:35:18 +0100
committer Olivier Galibert <galibert@pobox.com>2014-11-09 20:35:42 +0100
commit299bec581a976174ac2768ac0f966b56c3d8b6c0 (patch)
treeb561af88d321acfc4237b6d56e9e2b67a356d096
parent822fe9bfa0946e29171cc4736b80a6ab20ec9bcb (diff)
pentium: Some stuff to make lindbergh go further [O. Galibert]
-rw-r--r--src/emu/cpu/i386/i386.c10
-rw-r--r--src/emu/cpu/i386/i386.h3
-rw-r--r--src/emu/cpu/i386/i386ops.inc2
-rw-r--r--src/emu/cpu/i386/i386priv.h31
-rw-r--r--src/emu/cpu/i386/pentops.inc54
5 files changed, 94 insertions, 6 deletions
diff --git a/src/emu/cpu/i386/i386.c b/src/emu/cpu/i386/i386.c
index 32374631565..9e4494500bf 100644
--- a/src/emu/cpu/i386/i386.c
+++ b/src/emu/cpu/i386/i386.c
@@ -3148,7 +3148,7 @@ void i386_device::i386_common_init(int tlbsize)
zero_state();
- save_item(NAME( m_reg.d));
+ save_item(NAME(m_reg.d));
save_item(NAME(m_sreg[ES].selector));
save_item(NAME(m_sreg[ES].base));
save_item(NAME(m_sreg[ES].limit));
@@ -3190,9 +3190,9 @@ void i386_device::i386_common_init(int tlbsize)
save_item(NAME(m_AF));
save_item(NAME(m_IF));
save_item(NAME(m_TF));
- save_item(NAME( m_cr));
- save_item(NAME( m_dr));
- save_item(NAME( m_tr));
+ save_item(NAME(m_cr));
+ save_item(NAME(m_dr));
+ save_item(NAME(m_tr));
save_item(NAME(m_idtr.base));
save_item(NAME(m_idtr.limit));
save_item(NAME(m_gdtr.base));
@@ -3512,6 +3512,7 @@ void i386_device::zero_state()
m_ext = 0;
m_halted = 0;
m_operand_size = 0;
+ m_xmm_operand_size = 0;
m_address_size = 0;
m_operand_prefix = 0;
m_address_prefix = 0;
@@ -3765,6 +3766,7 @@ void i386_device::execute_run()
{
i386_check_irq_line();
m_operand_size = m_sreg[CS].d;
+ m_xmm_operand_size = 0;
m_address_size = m_sreg[CS].d;
m_operand_prefix = 0;
m_address_prefix = 0;
diff --git a/src/emu/cpu/i386/i386.h b/src/emu/cpu/i386/i386.h
index 235d6e898d5..d3c158d16d3 100644
--- a/src/emu/cpu/i386/i386.h
+++ b/src/emu/cpu/i386/i386.h
@@ -187,6 +187,7 @@ struct I386_CALL_GATE
int m_halted;
int m_operand_size;
+ int m_xmm_operand_size;
int m_address_size;
int m_operand_prefix;
int m_address_prefix;
@@ -331,6 +332,8 @@ struct I386_CALL_GATE
void pentium_msr_write(UINT32 offset, UINT64 data, UINT8 *valid_msr);
UINT64 p6_msr_read(UINT32 offset,UINT8 *valid_msr);
void p6_msr_write(UINT32 offset, UINT64 data, UINT8 *valid_msr);
+ UINT64 piv_msr_read(UINT32 offset,UINT8 *valid_msr);
+ void piv_msr_write(UINT32 offset, UINT64 data, UINT8 *valid_msr);
inline UINT64 MSR_READ(UINT32 offset,UINT8 *valid_msr);
inline void MSR_WRITE(UINT32 offset, UINT64 data, UINT8 *valid_msr);
UINT32 i386_load_protected_mode_segment(I386_SREG *seg, UINT64 *desc );
diff --git a/src/emu/cpu/i386/i386ops.inc b/src/emu/cpu/i386/i386ops.inc
index 8d4cc59b5b5..e4c2e4634d0 100644
--- a/src/emu/cpu/i386/i386ops.inc
+++ b/src/emu/cpu/i386/i386ops.inc
@@ -1134,6 +1134,7 @@ void i386_device::i386_repeat(int invert_flag)
break;
case 0x66:
m_operand_size ^= 1;
+ m_xmm_operand_size ^= 1;
break;
case 0x67:
m_address_size ^= 1;
@@ -2286,6 +2287,7 @@ void i386_device::i386_operand_size() // Opcode prefix 0x66
if(m_operand_prefix == 0)
{
m_operand_size ^= 1;
+ m_xmm_operand_size ^= 1;
m_operand_prefix = 1;
}
m_opcode = FETCH();
diff --git a/src/emu/cpu/i386/i386priv.h b/src/emu/cpu/i386/i386priv.h
index 5c24b86d3e4..d1fbb4372b6 100644
--- a/src/emu/cpu/i386/i386priv.h
+++ b/src/emu/cpu/i386/i386priv.h
@@ -1328,6 +1328,31 @@ void i386_device::p6_msr_write(UINT32 offset, UINT64 data, UINT8 *valid_msr)
}
}
+
+// PIV (Pentium 4+)
+UINT64 i386_device::piv_msr_read(UINT32 offset,UINT8 *valid_msr)
+{
+ switch(offset)
+ {
+ default:
+ logerror("RDMSR: unimplemented register called %08x at %08x\n",offset,m_pc-2);
+ *valid_msr = 1;
+ return 0;
+ }
+ return -1;
+}
+
+void i386_device::piv_msr_write(UINT32 offset, UINT64 data, UINT8 *valid_msr)
+{
+ switch(offset)
+ {
+ default:
+ logerror("WRMSR: unimplemented register called %08x (%08x%08x) at %08x\n",offset,(UINT32)(data >> 32),(UINT32)data,m_pc-2);
+ *valid_msr = 1;
+ break;
+ }
+}
+
UINT64 i386_device::MSR_READ(UINT32 offset,UINT8 *valid_msr)
{
UINT64 res;
@@ -1343,6 +1368,9 @@ UINT64 i386_device::MSR_READ(UINT32 offset,UINT8 *valid_msr)
case 6: // Pentium Pro, Pentium II, Pentium III
res = p6_msr_read(offset,valid_msr);
break;
+ case 15: // Pentium 4+
+ res = piv_msr_read(offset,valid_msr);
+ break;
default:
res = 0;
break;
@@ -1364,6 +1392,9 @@ void i386_device::MSR_WRITE(UINT32 offset, UINT64 data, UINT8 *valid_msr)
case 6: // Pentium Pro, Pentium II, Pentium III
p6_msr_write(offset,data,valid_msr);
break;
+ case 15: // Pentium 4+
+ piv_msr_write(offset,data,valid_msr);
+ break;
}
}
diff --git a/src/emu/cpu/i386/pentops.inc b/src/emu/cpu/i386/pentops.inc
index 101bad73c64..9545d20c285 100644
--- a/src/emu/cpu/i386/pentops.inc
+++ b/src/emu/cpu/i386/pentops.inc
@@ -1269,10 +1269,60 @@ void i386_device::mmx_group_0f73() // Opcode 0f 73
switch ( (modm & 0x38) >> 3 )
{
case 2: // psrlq
- MMX(modm & 7).q=MMX(modm & 7).q >> imm8;
+ if (m_xmm_operand_size)
+ {
+ XMM(modm & 7).q[0] = imm8 > 63 ? 0 : XMM(modm & 7).q[0] >> imm8;
+ XMM(modm & 7).q[1] = imm8 > 63 ? 0 : XMM(modm & 7).q[1] >> imm8;
+ }
+ else
+ MMX(modm & 7).q = imm8 > 63 ? 0 : MMX(modm & 7).q >> imm8;
+ break;
+ case 3: // psrldq
+ if (imm8 >= 16)
+ {
+ XMM(modm & 7).q[0] = 0;
+ XMM(modm & 7).q[1] = 0;
+ }
+ else if(imm8 >= 8)
+ {
+ imm8 = (imm8 & 7) << 3;
+ XMM(modm & 7).q[0] = XMM(modm & 7).q[1] >> imm8;
+ XMM(modm & 7).q[1] = 0;
+ }
+ else if(imm8)
+ {
+ imm8 = imm8 << 3;
+ XMM(modm & 7).q[1] = (XMM(modm & 7).q[0] << (64 - imm8)) | (XMM(modm & 7).q[1] >> imm8);
+ XMM(modm & 7).q[0] = XMM(modm & 7).q[0] >> imm8;
+ }
break;
case 6: // psllq
- MMX(modm & 7).q=MMX(modm & 7).q << imm8;
+ if (m_xmm_operand_size)
+ {
+ XMM(modm & 7).q[0] = imm8 > 63 ? 0 : XMM(modm & 7).q[0] << imm8;
+ XMM(modm & 7).q[1] = imm8 > 63 ? 0 : XMM(modm & 7).q[1] << imm8;
+ }
+ else
+ MMX(modm & 7).q = imm8 > 63 ? 0 : MMX(modm & 7).q << imm8;
+ break;
+ case 7: // pslldq
+ if (imm8 >= 16)
+ {
+ XMM(modm & 7).q[0] = 0;
+ XMM(modm & 7).q[1] = 0;
+ }
+ else if(imm8 >= 8)
+ {
+ imm8 = (imm8 & 7) << 3;
+ XMM(modm & 7).q[1] = XMM(modm & 7).q[0] << imm8;
+ XMM(modm & 7).q[0] = 0;
+ }
+ else if(imm8)
+ {
+ imm8 = imm8 << 3;
+ XMM(modm & 7).q[0] = (XMM(modm & 7).q[1] << (64 - imm8)) | (XMM(modm & 7).q[0] >> imm8);
+ XMM(modm & 7).q[1] = XMM(modm & 7).q[1] << imm8;
+ }
break;
default:
report_invalid_modrm("mmx_group0f73", modm);