mediagx: implement missing opcodes

but no disassembly because I don't understand it.
swe1pb (at least) boots to CMOS checksum failure prompt now.  I didn't
trace further.
This commit is contained in:
Peter Ferrie 2015-03-19 20:03:31 -07:00
parent 019e37e938
commit 633ab90d90
3 changed files with 285 additions and 0 deletions

View File

@ -962,6 +962,7 @@ struct I386_CALL_GATE
void pentium_cmovg_r32_rm32();
void pentium_movnti_m16_r16();
void pentium_movnti_m32_r32();
void i386_cyrix_special();
void i386_cyrix_unknown();
void pentium_cmpxchg8b_m64();
void pentium_movntq_m64_r64();
@ -1004,6 +1005,12 @@ struct I386_CALL_GATE
void mmx_paddw_r64_rm64();
void mmx_paddd_r64_rm64();
void mmx_emms();
void i386_cyrix_svdc();
void i386_cyrix_rsdc();
void i386_cyrix_svldt();
void i386_cyrix_rsldt();
void i386_cyrix_svts();
void i386_cyrix_rsts();
void mmx_movd_r64_rm32();
void mmx_movq_r64_rm64();
void mmx_movd_rm32_r64();

View File

@ -329,6 +329,10 @@ const i386_device::X86_OPCODE i386_device::s_x86_opcode_table[] =
{ 0x32, OP_2BYTE|OP_PENTIUM, &i386_device::pentium_rdmsr, &i386_device::pentium_rdmsr, false},
{ 0x38, OP_2BYTE|OP_PENTIUM, &i386_device::i386_decode_three_byte38, &i386_device::i386_decode_three_byte38,false},
{ 0x3A, OP_2BYTE|OP_PENTIUM, &i386_device::i386_decode_three_byte3a, &i386_device::i386_decode_three_byte3a,false},
{ 0x3A, OP_2BYTE|OP_CYRIX, &i386_device::i386_cyrix_special, &i386_device::i386_cyrix_special, false},
{ 0x3B, OP_2BYTE|OP_CYRIX, &i386_device::i386_cyrix_special, &i386_device::i386_cyrix_special, false},
{ 0x3C, OP_2BYTE|OP_CYRIX, &i386_device::i386_cyrix_special, &i386_device::i386_cyrix_special, false},
{ 0x3D, OP_2BYTE|OP_CYRIX, &i386_device::i386_cyrix_special, &i386_device::i386_cyrix_special, false},
{ 0x40, OP_2BYTE|OP_PENTIUM, &i386_device::pentium_cmovo_r16_rm16, &i386_device::pentium_cmovo_r32_rm32, false},
{ 0x41, OP_2BYTE|OP_PENTIUM, &i386_device::pentium_cmovno_r16_rm16, &i386_device::pentium_cmovno_r32_rm32, false},
{ 0x42, OP_2BYTE|OP_PENTIUM, &i386_device::pentium_cmovb_r16_rm16, &i386_device::pentium_cmovb_r32_rm32, false},
@ -384,6 +388,12 @@ const i386_device::X86_OPCODE i386_device::s_x86_opcode_table[] =
{ 0x75, OP_2BYTE|OP_MMX, &i386_device::mmx_pcmpeqw_r64_rm64, &i386_device::mmx_pcmpeqw_r64_rm64, false},
{ 0x76, OP_2BYTE|OP_MMX, &i386_device::mmx_pcmpeqd_r64_rm64, &i386_device::mmx_pcmpeqd_r64_rm64, false},
{ 0x77, OP_2BYTE|OP_MMX, &i386_device::mmx_emms, &i386_device::mmx_emms, false},
{ 0x78, OP_2BYTE|OP_CYRIX, &i386_device::i386_cyrix_svdc, &i386_device::i386_cyrix_svdc, false},
{ 0x79, OP_2BYTE|OP_CYRIX, &i386_device::i386_cyrix_rsdc, &i386_device::i386_cyrix_rsdc, false},
{ 0x7a, OP_2BYTE|OP_CYRIX, &i386_device::i386_cyrix_svldt, &i386_device::i386_cyrix_svldt, false},
{ 0x7b, OP_2BYTE|OP_CYRIX, &i386_device::i386_cyrix_rsldt, &i386_device::i386_cyrix_rsldt, false},
{ 0x7c, OP_2BYTE|OP_CYRIX, &i386_device::i386_cyrix_svts, &i386_device::i386_cyrix_svts, false},
{ 0x7d, OP_2BYTE|OP_CYRIX, &i386_device::i386_cyrix_rsts, &i386_device::i386_cyrix_rsts, false},
{ 0x7e, OP_2BYTE|OP_MMX, &i386_device::mmx_movd_rm32_r64, &i386_device::mmx_movd_rm32_r64, false},
{ 0x7f, OP_2BYTE|OP_MMX, &i386_device::mmx_movq_rm64_r64, &i386_device::mmx_movq_rm64_r64, false},
{ 0x80, OP_2BYTE|OP_I386, &i386_device::i386_jo_rel16, &i386_device::i386_jo_rel32, false},

View File

@ -1062,6 +1062,18 @@ void i386_device::pentium_movnti_m32_r32() // Opcode 0f c3
}
}
void i386_device::i386_cyrix_special() // Opcode 0x0f 3a-3d
{
/*
0f 3a BB0_RESET (set BB0 pointer = base)
0f 3b BB1_RESET (set BB1 pointer = base)
0f 3c CPU_WRITE (write special CPU memory-mapped register, [ebx] = eax)
0f 3d CPU_READ (read special CPU memory-mapped register, eax, = [ebx])
*/
CYCLES(1);
}
void i386_device::i386_cyrix_unknown() // Opcode 0x0f 74
{
logerror("Unemulated 0x0f 0x74 opcode called\n");
@ -1970,6 +1982,262 @@ void i386_device::mmx_emms() // Opcode 0f 77
CYCLES(1); // TODO: correct cycle count
}
void i386_device::i386_cyrix_svdc() // Opcode 0f 78
{
UINT8 modrm = FETCH();
if( modrm < 0xc0 ) {
UINT32 ea = GetEA(modrm,0);
int index = (modrm >> 3) & 7;
int limit;
switch (index)
{
case 0:
{
index = ES;
break;
}
case 2:
{
index = SS;
break;
}
case 3:
{
index = DS;
break;
}
case 4:
{
index = FS;
break;
}
case 5:
{
index = GS;
break;
}
default:
{
i386_trap(6, 0, 0);
}
}
limit = m_sreg[index].limit;
if (m_sreg[index].flags & 0x8000) //G bit
{
limit >>= 12;
}
WRITE16(ea + 0, limit);
WRITE32(ea + 2, m_sreg[index].base);
WRITE16(ea + 5, m_sreg[index].flags); //replace top 8 bits of base
WRITE8(ea + 7, m_sreg[index].base >> 24);
WRITE16(ea + 8, m_sreg[index].selector);
} else {
i386_trap(6, 0, 0);
}
CYCLES(1); // TODO: correct cycle count
}
void i386_device::i386_cyrix_rsdc() // Opcode 0f 79
{
UINT8 modrm = FETCH();
if( modrm < 0xc0 ) {
UINT32 ea = GetEA(modrm,0);
int index = (modrm >> 3) & 7;
UINT16 flags;
UINT32 base;
UINT32 limit;
switch (index)
{
case 0:
{
index = ES;
break;
}
case 2:
{
index = SS;
break;
}
case 3:
{
index = DS;
break;
}
case 4:
{
index = FS;
break;
}
case 5:
{
index = GS;
break;
}
default:
{
i386_trap(6, 0, 0);
}
}
base = (READ32(ea + 2) & 0x00ffffff) | (READ8(ea + 7) << 24);
flags = READ16(ea + 5);
limit = READ16(ea + 0) | ((flags & 3) << 16);
if (flags & 0x8000) //G bit
{
limit = (limit << 12) | 0xfff;
}
m_sreg[index].selector = READ16(ea + 8);
m_sreg[index].flags = flags;
m_sreg[index].base = base;
m_sreg[index].limit = limit;
} else {
i386_trap(6, 0, 0);
}
CYCLES(1); // TODO: correct cycle count
}
void i386_device::i386_cyrix_svldt() // Opcode 0f 7a
{
if ( PROTECTED_MODE && !V8086_MODE )
{
UINT8 modrm = FETCH();
if( !(modrm & 0xf8) ) {
UINT32 ea = GetEA(modrm,0);
UINT32 limit = m_ldtr.limit;
if (m_ldtr.flags & 0x8000) //G bit
{
limit >>= 12;
}
WRITE16(ea + 0, limit);
WRITE32(ea + 2, m_ldtr.base);
WRITE16(ea + 5, m_ldtr.flags); //replace top 8 bits of base
WRITE8(ea + 7, m_ldtr.base >> 24);
WRITE16(ea + 8, m_ldtr.segment);
} else {
i386_trap(6, 0, 0);
}
} else {
i386_trap(6, 0, 0);
}
CYCLES(1); // TODO: correct cycle count
}
void i386_device::i386_cyrix_rsldt() // Opcode 0f 7b
{
if ( PROTECTED_MODE && !V8086_MODE )
{
if(m_CPL)
FAULT(FAULT_GP,0)
UINT8 modrm = FETCH();
if( !(modrm & 0xf8) ) {
UINT32 ea = GetEA(modrm,0);
UINT16 flags = READ16(ea + 5);
UINT32 base = (READ32(ea + 2) | 0x00ffffff) | (READ8(ea + 7) << 24);
UINT32 limit = READ16(ea + 0) | ((flags & 3) << 16);
I386_SREG seg;
if (flags & 0x8000) //G bit
{
limit = (limit << 12) | 0xfff;
}
memset(&seg, 0, sizeof(seg));
seg.selector = READ16(ea + 8);
i386_load_protected_mode_segment(&seg,NULL);
m_ldtr.limit = limit;
m_ldtr.base = base;
m_ldtr.flags = flags;
} else {
i386_trap(6, 0, 0);
}
} else {
i386_trap(6, 0, 0);
}
CYCLES(1); // TODO: correct cycle count
}
void i386_device::i386_cyrix_svts() // Opcode 0f 7c
{
if ( PROTECTED_MODE )
{
UINT8 modrm = FETCH();
if( !(modrm & 0xf8) ) {
UINT32 ea = GetEA(modrm,0);
UINT32 limit = m_task.limit;
if (m_task.flags & 0x8000) //G bit
{
limit >>= 12;
}
WRITE16(ea + 0, limit);
WRITE32(ea + 2, m_task.base);
WRITE16(ea + 5, m_task.flags); //replace top 8 bits of base
WRITE8(ea + 7, m_task.base >> 24);
WRITE16(ea + 8, m_task.segment);
} else {
i386_trap(6, 0, 0);
}
} else {
i386_trap(6, 0, 0);
}
}
void i386_device::i386_cyrix_rsts() // Opcode 0f 7d
{
if ( PROTECTED_MODE )
{
if(m_CPL)
FAULT(FAULT_GP,0)
UINT8 modrm = FETCH();
if( !(modrm & 0xf8) ) {
UINT32 ea = GetEA(modrm,0);
UINT16 flags = READ16(ea + 5);
UINT32 base = (READ32(ea + 2) | 0x00ffffff) | (READ8(ea + 7) << 24);
UINT32 limit = READ16(ea + 0) | ((flags & 3) << 16);
if (flags & 0x8000) //G bit
{
limit = (limit << 12) | 0xfff;
}
m_task.segment = READ16(ea + 8);
m_task.limit = limit;
m_task.base = base;
m_task.flags = flags;
} else {
i386_trap(6, 0, 0);
}
} else {
i386_trap(6, 0, 0);
}
CYCLES(1); // TODO: correct cycle count
}
void i386_device::mmx_movd_r64_rm32() // Opcode 0f 6e
{
MMXPROLOG();