1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
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);
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);
}
|