summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/i386/pentops.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/i386/pentops.c')
-rw-r--r--trunk/src/emu/cpu/i386/pentops.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/i386/pentops.c b/trunk/src/emu/cpu/i386/pentops.c
new file mode 100644
index 00000000000..f16cbb6ef75
--- /dev/null
+++ b/trunk/src/emu/cpu/i386/pentops.c
@@ -0,0 +1,88 @@
+// Pentium+ specific opcodes
+
+static void PENTIUMOP(rdmsr)(i386_state *cpustate) // Opcode 0x0f 32
+{
+ UINT64 data;
+ UINT8 valid_msr = 0;
+
+ data = MSR_READ(cpustate,REG32(ECX),&valid_msr);
+ REG32(EDX) = data >> 32;
+ REG32(EAX) = data & 0xffffffff;
+
+ if(cpustate->CPL != 0 || valid_msr == 0) // if current privilege level isn't 0 or the register isn't recognized ...
+ FAULT(FAULT_GP,0) // ... throw a general exception fault
+
+ CYCLES(cpustate,CYCLES_RDMSR);
+}
+
+static void PENTIUMOP(wrmsr)(i386_state *cpustate) // Opcode 0x0f 30
+{
+ UINT64 data;
+ UINT8 valid_msr = 0;
+
+ data = (UINT64)REG32(EAX);
+ data |= (UINT64)(REG32(EDX)) << 32;
+
+ MSR_WRITE(cpustate,REG32(ECX),data,&valid_msr);
+
+ if(cpustate->CPL != 0 || valid_msr == 0) // if current privilege level isn't 0 or the register isn't recognized
+ FAULT(FAULT_GP,0) // ... throw a general exception fault
+
+ CYCLES(cpustate,1); // TODO: correct cycle count (~30-45)
+}
+
+static void PENTIUMOP(rdtsc)(i386_state *cpustate) // Opcode 0x0f 31
+{
+ UINT64 ts = cpustate->tsc + (cpustate->base_cycles - cpustate->cycles);
+ REG32(EAX) = (UINT32)(ts);
+ REG32(EDX) = (UINT32)(ts >> 32);
+
+ CYCLES(cpustate,CYCLES_RDTSC);
+}
+
+static void I386OP(cyrix_unknown)(i386_state *cpustate) // Opcode 0x0f 74
+{
+ logerror("Unemulated 0x0f 0x74 opcode called\n");
+
+ CYCLES(cpustate,1);
+}
+
+static void PENTIUMOP(cmpxchg8b_m64)(i386_state *cpustate) // Opcode 0x0f c7
+{
+ UINT8 modm = FETCH(cpustate);
+ if( modm >= 0xc0 ) {
+ fatalerror("pentium: cmpxchg8b_m64 - invalid modm");
+ } else {
+ UINT32 ea = GetEA(cpustate,modm,0);
+ UINT64 value = READ64(cpustate,ea);
+ UINT64 edx_eax = (((UINT64) REG32(EDX)) << 32) | REG32(EAX);
+ UINT64 ecx_ebx = (((UINT64) REG32(ECX)) << 32) | REG32(EBX);
+
+ if( value == edx_eax ) {
+ WRITE64(cpustate,ea, ecx_ebx);
+ cpustate->ZF = 1;
+ CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
+ } else {
+ REG32(EDX) = (UINT32) (value >> 32);
+ REG32(EAX) = (UINT32) (value >> 0);
+ cpustate->ZF = 0;
+ CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
+ }
+ }
+}
+
+static void PENTIUMOP(sse_group0fae)(i386_state *cpustate) // Opcode 0x0f ae
+{
+ UINT8 modm = FETCH(cpustate);
+ if( modm == 0xf8 ) {
+ logerror("Unemulated SFENCE opcode called\n");
+ CYCLES(cpustate,1); // sfence instruction
+ } else {
+ fatalerror("pentium: bad/unsupported 0f ae opcode");
+ }
+}
+
+static void PENTIUMOP(ud2)(i386_state *cpustate) // Opcode 0x0f 0b
+{
+ i386_trap(cpustate, 6, 0, 0);
+}