mirror of
https://github.com/holub/mame
synced 2025-05-24 14:56:21 +03:00
Various changes to i386 CPU core and Chihiro emulation, allowing it to show a basic logo and text [Samuele Zannoli]
This commit is contained in:
parent
c2a46ad456
commit
58a33d8b36
@ -2699,9 +2699,37 @@ static void build_cycle_table(running_machine &machine)
|
||||
}
|
||||
}
|
||||
|
||||
static void report_invalid_opcode(i386_state *cpustate)
|
||||
{
|
||||
#ifndef DEBUG_MISSING_OPCODE
|
||||
logerror("i386: Invalid opcode %02X at %08X\n", cpustate->opcode, cpustate->pc - 1);
|
||||
#else
|
||||
logerror("i386: Invalid opcode");
|
||||
for (int a = 0; a < cpustate->opcode_bytes_length; a++)
|
||||
logerror(" %02X", cpustate->opcode_bytes[a]);
|
||||
logerror(" at %08X\n", cpustate->opcode_pc);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void report_unimplemented_opcode(i386_state *cpustate)
|
||||
{
|
||||
#ifndef DEBUG_MISSING_OPCODE
|
||||
fatalerror("i386: Unimplemented opcode %02X at %08X", cpustate->opcode, cpustate->pc - 1 );
|
||||
#else
|
||||
astring errmsg;
|
||||
errmsg.cat("i386: Unimplemented opcode ");
|
||||
for (int a = 0; a < cpustate->opcode_bytes_length; a++)
|
||||
errmsg.catprintf(" %02X", cpustate->opcode_bytes[a]);
|
||||
errmsg.catprintf(" at %08X", cpustate->opcode_pc );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Forward declarations */
|
||||
static void I386OP(decode_opcode)(i386_state *cpustate);
|
||||
static void I386OP(decode_two_byte)(i386_state *cpustate);
|
||||
static void I386OP(decode_three_byte66)(i386_state *cpustate);
|
||||
static void I386OP(decode_three_bytef2)(i386_state *cpustate);
|
||||
static void I386OP(decode_three_bytef3)(i386_state *cpustate);
|
||||
|
||||
|
||||
|
||||
@ -2732,6 +2760,36 @@ static void I386OP(decode_two_byte)(i386_state *cpustate)
|
||||
cpustate->opcode_table2_16[cpustate->opcode](cpustate);
|
||||
}
|
||||
|
||||
/* Three-byte opcode prefix 66 0f */
|
||||
static void I386OP(decode_three_byte66)(i386_state *cpustate)
|
||||
{
|
||||
cpustate->opcode = FETCH(cpustate);
|
||||
if( cpustate->operand_size )
|
||||
cpustate->opcode_table366_32[cpustate->opcode](cpustate);
|
||||
else
|
||||
cpustate->opcode_table366_16[cpustate->opcode](cpustate);
|
||||
}
|
||||
|
||||
/* Three-byte opcode prefix f2 0f */
|
||||
static void I386OP(decode_three_bytef2)(i386_state *cpustate)
|
||||
{
|
||||
cpustate->opcode = FETCH(cpustate);
|
||||
if( cpustate->operand_size )
|
||||
cpustate->opcode_table3f2_32[cpustate->opcode](cpustate);
|
||||
else
|
||||
cpustate->opcode_table3f2_16[cpustate->opcode](cpustate);
|
||||
}
|
||||
|
||||
/* Three-byte opcode prefix f3 0f */
|
||||
static void I386OP(decode_three_bytef3)(i386_state *cpustate)
|
||||
{
|
||||
cpustate->opcode = FETCH(cpustate);
|
||||
if( cpustate->operand_size )
|
||||
cpustate->opcode_table3f3_32[cpustate->opcode](cpustate);
|
||||
else
|
||||
cpustate->opcode_table3f3_16[cpustate->opcode](cpustate);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static UINT64 i386_debug_segbase(symbol_table &table, void *ref, int params, const UINT64 *param)
|
||||
@ -2876,6 +2934,7 @@ static CPU_INIT( i386 )
|
||||
device->save_item(NAME(cpustate->ldtr.flags));
|
||||
device->save_item(NAME(cpustate->irq_state));
|
||||
device->save_item(NAME(cpustate->performed_intersegment_jump));
|
||||
device->save_item(NAME(cpustate->mxcsr));
|
||||
device->machine().save().register_postload(save_prepost_delegate(FUNC(i386_postload), cpustate));
|
||||
}
|
||||
|
||||
@ -2888,6 +2947,12 @@ static void build_opcode_table(i386_state *cpustate, UINT32 features)
|
||||
cpustate->opcode_table1_32[i] = I386OP(invalid);
|
||||
cpustate->opcode_table2_16[i] = I386OP(invalid);
|
||||
cpustate->opcode_table2_32[i] = I386OP(invalid);
|
||||
cpustate->opcode_table366_16[i] = I386OP(invalid);
|
||||
cpustate->opcode_table366_32[i] = I386OP(invalid);
|
||||
cpustate->opcode_table3f2_16[i] = I386OP(invalid);
|
||||
cpustate->opcode_table3f2_32[i] = I386OP(invalid);
|
||||
cpustate->opcode_table3f3_16[i] = I386OP(invalid);
|
||||
cpustate->opcode_table3f3_32[i] = I386OP(invalid);
|
||||
}
|
||||
|
||||
for (i=0; i < sizeof(x86_opcode_table)/sizeof(X86_OPCODE); i++)
|
||||
@ -2900,6 +2965,23 @@ static void build_opcode_table(i386_state *cpustate, UINT32 features)
|
||||
{
|
||||
cpustate->opcode_table2_32[op->opcode] = op->handler32;
|
||||
cpustate->opcode_table2_16[op->opcode] = op->handler16;
|
||||
cpustate->opcode_table366_32[op->opcode] = op->handler32;
|
||||
cpustate->opcode_table366_16[op->opcode] = op->handler16;
|
||||
}
|
||||
else if (op->flags & OP_3BYTE66)
|
||||
{
|
||||
cpustate->opcode_table366_32[op->opcode] = op->handler32;
|
||||
cpustate->opcode_table366_16[op->opcode] = op->handler16;
|
||||
}
|
||||
else if (op->flags & OP_3BYTEF2)
|
||||
{
|
||||
cpustate->opcode_table3f2_32[op->opcode] = op->handler32;
|
||||
cpustate->opcode_table3f2_16[op->opcode] = op->handler16;
|
||||
}
|
||||
else if (op->flags & OP_3BYTEF3)
|
||||
{
|
||||
cpustate->opcode_table3f3_32[op->opcode] = op->handler32;
|
||||
cpustate->opcode_table3f3_16[op->opcode] = op->handler16;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3026,6 +3108,10 @@ static CPU_EXECUTE( i386 )
|
||||
cpustate->IF = 1;
|
||||
cpustate->delayed_interrupt_enable = 0;
|
||||
}
|
||||
#ifdef DEBUG_MISSING_OPCODE
|
||||
cpustate->opcode_bytes_length = 0;
|
||||
cpustate->opcode_pc = cpustate->pc;
|
||||
#endif
|
||||
try
|
||||
{
|
||||
I386OP(decode_opcode)(cpustate);
|
||||
@ -3531,10 +3617,11 @@ static CPU_RESET( pentium )
|
||||
|
||||
cpustate->a20_mask = ~0;
|
||||
|
||||
cpustate->cr[0] = 0x00000010;
|
||||
cpustate->cr[0] = 0x60000010;
|
||||
cpustate->eflags = 0x00200000;
|
||||
cpustate->eflags_mask = 0x003f7fd7;
|
||||
cpustate->eip = 0xfff0;
|
||||
cpustate->mxcsr = 0x1f80;
|
||||
|
||||
x87_reset(cpustate);
|
||||
|
||||
@ -3545,7 +3632,7 @@ static CPU_RESET( pentium )
|
||||
REG32(EAX) = 0;
|
||||
REG32(EDX) = (5 << 8) | (2 << 4) | (5);
|
||||
|
||||
build_opcode_table(cpustate, OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM);
|
||||
build_opcode_table(cpustate, OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_MMX | OP_SSE);
|
||||
build_x87_opcode_table(get_safe_token(device));
|
||||
cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM];
|
||||
cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM];
|
||||
|
@ -1088,6 +1088,13 @@ static void I386OP(repeat)(i386_state *cpustate, int invert_flag)
|
||||
repeated_pc = cpustate->pc;
|
||||
opcode = FETCH(cpustate);
|
||||
switch(opcode) {
|
||||
case 0x0f:
|
||||
if (invert_flag == 0)
|
||||
I386OP(decode_three_bytef3)(cpustate); // sse f3 0f
|
||||
else
|
||||
I386OP(decode_three_bytef2)(cpustate); // sse f2 0f
|
||||
return;
|
||||
break;
|
||||
case 0x26:
|
||||
cpustate->segment_override=ES;
|
||||
cpustate->segment_prefix=1;
|
||||
@ -2252,14 +2259,23 @@ static void I386OP(segment_SS)(i386_state *cpustate) // Opcode 0x36
|
||||
I386OP(decode_opcode)(cpustate);
|
||||
}
|
||||
|
||||
static void I386OP(operand_size)(i386_state *cpustate) // Opcode 0x66
|
||||
static void I386OP(operand_size)(i386_state *cpustate) // Opcode prefix 0x66
|
||||
{
|
||||
if(cpustate->operand_prefix == 0)
|
||||
{
|
||||
cpustate->operand_size ^= 1;
|
||||
cpustate->operand_prefix = 1;
|
||||
}
|
||||
I386OP(decode_opcode)(cpustate);
|
||||
cpustate->opcode = FETCH(cpustate);
|
||||
if (cpustate->opcode == 0x0f)
|
||||
I386OP(decode_three_byte66)(cpustate);
|
||||
else
|
||||
{
|
||||
if( cpustate->operand_size )
|
||||
cpustate->opcode_table1_32[cpustate->opcode](cpustate);
|
||||
else
|
||||
cpustate->opcode_table1_16[cpustate->opcode](cpustate);
|
||||
}
|
||||
}
|
||||
|
||||
static void I386OP(address_size)(i386_state *cpustate) // Opcode 0x67
|
||||
@ -2465,11 +2481,11 @@ static void I386OP(loadall)(i386_state *cpustate) // Opcode 0x0f 0x07 (0x0f 0x0
|
||||
|
||||
static void I386OP(unimplemented)(i386_state *cpustate)
|
||||
{
|
||||
fatalerror("i386: Unimplemented opcode %02X at %08X", cpustate->opcode, cpustate->pc - 1 );
|
||||
report_unimplemented_opcode(cpustate);
|
||||
}
|
||||
|
||||
static void I386OP(invalid)(i386_state *cpustate)
|
||||
{
|
||||
logerror("i386: Invalid opcode %02X at %08X\n", cpustate->opcode, cpustate->pc - 1);
|
||||
report_invalid_opcode(cpustate);
|
||||
i386_trap(cpustate, 6, 0, 0);
|
||||
}
|
||||
|
@ -16,6 +16,9 @@ typedef struct {
|
||||
#define OP_SSE3 0x100
|
||||
#define OP_CYRIX 0x8000
|
||||
#define OP_2BYTE 0x80000000
|
||||
#define OP_3BYTE66 0x40000000
|
||||
#define OP_3BYTEF2 0x20000000
|
||||
#define OP_3BYTEF3 0x10000000
|
||||
|
||||
static const X86_OPCODE x86_opcode_table[] =
|
||||
{
|
||||
@ -284,6 +287,7 @@ static const X86_OPCODE x86_opcode_table[] =
|
||||
{ 0xFD, OP_I386, I386OP(std), I386OP(std), },
|
||||
{ 0xFE, OP_I386, I386OP(groupFE_8), I386OP(groupFE_8), },
|
||||
{ 0xFF, OP_I386, I386OP(groupFF_16), I386OP(groupFF_32), },
|
||||
/* 0F ?? */
|
||||
{ 0x00, OP_2BYTE|OP_I386, I386OP(group0F00_16), I386OP(group0F00_32), },
|
||||
{ 0x01, OP_2BYTE|OP_I386, I386OP(group0F01_16), I386OP(group0F01_32), },
|
||||
{ 0x01, OP_2BYTE|OP_I486, I486OP(group0F01_16), I486OP(group0F01_32), },
|
||||
@ -300,10 +304,15 @@ static const X86_OPCODE x86_opcode_table[] =
|
||||
{ 0x23, OP_2BYTE|OP_I386, I386OP(mov_dr_r32), I386OP(mov_dr_r32), },
|
||||
{ 0x24, OP_2BYTE|OP_I386, I386OP(mov_r32_tr), I386OP(mov_r32_tr), },
|
||||
{ 0x26, OP_2BYTE|OP_I386, I386OP(mov_tr_r32), I386OP(mov_tr_r32), },
|
||||
{ 0x28, OP_2BYTE|OP_SSE, SSEOP(movaps_r128_rm128), SSEOP(movaps_r128_rm128), },
|
||||
{ 0x29, OP_2BYTE|OP_SSE, SSEOP(movaps_rm128_r128), SSEOP(movaps_rm128_r128), },
|
||||
{ 0x30, OP_2BYTE|OP_PENTIUM, PENTIUMOP(wrmsr), PENTIUMOP(wrmsr), },
|
||||
{ 0x31, OP_2BYTE|OP_PENTIUM, PENTIUMOP(rdtsc), PENTIUMOP(rdtsc), },
|
||||
{ 0x32, OP_2BYTE|OP_PENTIUM, PENTIUMOP(rdmsr), PENTIUMOP(rdmsr), },
|
||||
{ 0x58, OP_2BYTE|OP_SSE, SSEOP(addps), SSEOP(addps), },
|
||||
{ 0x59, OP_2BYTE|OP_SSE, SSEOP(mulps), SSEOP(mulps), },
|
||||
{ 0x74, OP_2BYTE|OP_CYRIX, I386OP(cyrix_unknown), I386OP(cyrix_unknown), },
|
||||
{ 0x77, OP_2BYTE|OP_MMX, MMXOP(emms), MMXOP(emms), },
|
||||
{ 0x80, OP_2BYTE|OP_I386, I386OP(jo_rel16), I386OP(jo_rel32), },
|
||||
{ 0x81, OP_2BYTE|OP_I386, I386OP(jno_rel16), I386OP(jno_rel32), },
|
||||
{ 0x82, OP_2BYTE|OP_I386, I386OP(jc_rel16), I386OP(jc_rel32), },
|
||||
@ -348,7 +357,7 @@ static const X86_OPCODE x86_opcode_table[] =
|
||||
{ 0xAB, OP_2BYTE|OP_I386, I386OP(bts_rm16_r16), I386OP(bts_rm32_r32), },
|
||||
{ 0xAC, OP_2BYTE|OP_I386, I386OP(shrd16_i8), I386OP(shrd32_i8), },
|
||||
{ 0xAD, OP_2BYTE|OP_I386, I386OP(shrd16_cl), I386OP(shrd32_cl), },
|
||||
{ 0xAE, OP_2BYTE|OP_PENTIUM, PENTIUMOP(sse_group0fae), PENTIUMOP(sse_group0fae), },
|
||||
{ 0xAE, OP_2BYTE|OP_SSE, SSEOP(sse_group0fae), SSEOP(sse_group0fae), },
|
||||
{ 0xAF, OP_2BYTE|OP_I386, I386OP(imul_r16_rm16), I386OP(imul_r32_rm32), },
|
||||
{ 0xB0, OP_2BYTE|OP_I486, I486OP(cmpxchg_rm8_r8), I486OP(cmpxchg_rm8_r8), },
|
||||
{ 0xB1, OP_2BYTE|OP_I486, I486OP(cmpxchg_rm16_r16), I486OP(cmpxchg_rm32_r32), },
|
||||
@ -366,6 +375,7 @@ static const X86_OPCODE x86_opcode_table[] =
|
||||
{ 0xBF, OP_2BYTE|OP_I386, I386OP(invalid), I386OP(movsx_r32_rm16), },
|
||||
{ 0xC0, OP_2BYTE|OP_I486, I486OP(xadd_rm8_r8), I486OP(xadd_rm8_r8), },
|
||||
{ 0xC1, OP_2BYTE|OP_I486, I486OP(xadd_rm16_r16), I486OP(xadd_rm32_r32), },
|
||||
{ 0xc6, OP_2BYTE|OP_SSE, SSEOP(shufps), SSEOP(shufps), },
|
||||
{ 0xC7, OP_2BYTE|OP_PENTIUM, PENTIUMOP(cmpxchg8b_m64), PENTIUMOP(cmpxchg8b_m64), },
|
||||
{ 0xC8, OP_2BYTE|OP_I486, I486OP(bswap_eax), I486OP(bswap_eax), },
|
||||
{ 0xC9, OP_2BYTE|OP_I486, I486OP(bswap_ecx), I486OP(bswap_ecx), },
|
||||
@ -374,5 +384,7 @@ static const X86_OPCODE x86_opcode_table[] =
|
||||
{ 0xCC, OP_2BYTE|OP_I486, I486OP(bswap_esp), I486OP(bswap_esp), },
|
||||
{ 0xCD, OP_2BYTE|OP_I486, I486OP(bswap_ebp), I486OP(bswap_ebp), },
|
||||
{ 0xCE, OP_2BYTE|OP_I486, I486OP(bswap_esi), I486OP(bswap_esi), },
|
||||
{ 0xCF, OP_2BYTE|OP_I486, I486OP(bswap_edi), I486OP(bswap_edi), }
|
||||
{ 0xCF, OP_2BYTE|OP_I486, I486OP(bswap_edi), I486OP(bswap_edi), },
|
||||
/* F3 0F ?? */
|
||||
{ 0x2C, OP_3BYTEF3|OP_SSE, SSEOP(cvttss2si), SSEOP(cvttss2si), }
|
||||
};
|
||||
|
@ -7,10 +7,13 @@
|
||||
#include "../../../lib/softfloat/milieu.h"
|
||||
#include "../../../lib/softfloat/softfloat.h"
|
||||
|
||||
//#define DEBUG_MISSING_OPCODE
|
||||
|
||||
#define I386OP(XX) i386_##XX
|
||||
#define I486OP(XX) i486_##XX
|
||||
#define PENTIUMOP(XX) pentium_##XX
|
||||
#define MMXOP(XX) mmx_##XX
|
||||
#define SSEOP(XX) sse_##XX
|
||||
|
||||
extern int i386_dasm_one(char *buffer, UINT32 pc, const UINT8 *oprom, int mode);
|
||||
|
||||
@ -150,7 +153,20 @@ enum
|
||||
X87_ST4,
|
||||
X87_ST5,
|
||||
X87_ST6,
|
||||
X87_ST7,
|
||||
X87_ST7
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
/* mmx registers aliased to x87 ones */
|
||||
MMX_MM0=X87_ST0,
|
||||
MMX_MM1=X87_ST1,
|
||||
MMX_MM2=X87_ST2,
|
||||
MMX_MM3=X87_ST3,
|
||||
MMX_MM4=X87_ST4,
|
||||
MMX_MM5=X87_ST5,
|
||||
MMX_MM6=X87_ST6,
|
||||
MMX_MM7=X87_ST7
|
||||
};
|
||||
|
||||
/* Protected mode exceptions */
|
||||
@ -164,6 +180,23 @@ enum
|
||||
#define FAULT_PF 14 // Page Fault
|
||||
#define FAULT_MF 16 // Match (Coprocessor) Fault
|
||||
|
||||
/* MXCSR Control and Status Register */
|
||||
#define MXCSR_IE (1<<0) // Invalid Operation Flag
|
||||
#define MXCSR_DE (1<<1) // Denormal Flag
|
||||
#define MXCSR_ZE (1<<2) // Divide-by-Zero Flag
|
||||
#define MXCSR_OE (1<<3) // Overflow Flag
|
||||
#define MXCSR_UE (1<<4) // Underflow Flag
|
||||
#define MXCSR_PE (1<<5) // Precision Flag
|
||||
#define MXCSR_DAZ (1<<6) // Denormals Are Zeros
|
||||
#define MXCSR_IM (1<<7) // Invalid Operation Mask
|
||||
#define MXCSR_DM (1<<8) // Denormal Operation Mask
|
||||
#define MXCSR_ZM (1<<9) // Divide-by-Zero Mask
|
||||
#define MXCSR_OM (1<<10) // Overflow Mask
|
||||
#define MXCSR_UM (1<<11) // Underflow Mask
|
||||
#define MXCSR_PM (1<<12) // Precision Mask
|
||||
#define MXCSR_RC (3<<13) // Rounding Control
|
||||
#define MXCSR_FZ (1<<15) // Flush to Zero
|
||||
|
||||
typedef struct {
|
||||
UINT16 selector;
|
||||
UINT16 flags;
|
||||
@ -207,6 +240,16 @@ typedef union {
|
||||
double f;
|
||||
} X87_REG;
|
||||
|
||||
typedef UINT64 MMX_REG;
|
||||
|
||||
typedef union {
|
||||
UINT32 d[4];
|
||||
UINT16 w[8];
|
||||
UINT8 b[16];
|
||||
UINT64 q[2];
|
||||
float f[4];
|
||||
} XMM_REG;
|
||||
|
||||
typedef struct _i386_state i386_state;
|
||||
struct _i386_state
|
||||
{
|
||||
@ -300,14 +343,30 @@ struct _i386_state
|
||||
void (*opcode_table_x87_de[256])(i386_state *cpustate, UINT8 modrm);
|
||||
void (*opcode_table_x87_df[256])(i386_state *cpustate, UINT8 modrm);
|
||||
|
||||
// SSE
|
||||
XMM_REG sse_reg[8];
|
||||
UINT32 mxcsr;
|
||||
|
||||
void (*opcode_table1_16[256])(i386_state *cpustate);
|
||||
void (*opcode_table1_32[256])(i386_state *cpustate);
|
||||
void (*opcode_table2_16[256])(i386_state *cpustate);
|
||||
void (*opcode_table2_32[256])(i386_state *cpustate);
|
||||
void (*opcode_table366_16[256])(i386_state *cpustate);
|
||||
void (*opcode_table366_32[256])(i386_state *cpustate);
|
||||
void (*opcode_table3f2_16[256])(i386_state *cpustate);
|
||||
void (*opcode_table3f2_32[256])(i386_state *cpustate);
|
||||
void (*opcode_table3f3_16[256])(i386_state *cpustate);
|
||||
void (*opcode_table3f3_32[256])(i386_state *cpustate);
|
||||
|
||||
UINT8 *cycle_table_pm;
|
||||
UINT8 *cycle_table_rm;
|
||||
|
||||
// bytes in current opcode, debug only
|
||||
#ifdef DEBUG_MISSING_OPCODE
|
||||
UINT8 opcode_bytes[16];
|
||||
UINT32 opcode_pc;
|
||||
int opcode_bytes_length;
|
||||
#endif
|
||||
};
|
||||
|
||||
INLINE i386_state *get_safe_token(device_t *device)
|
||||
@ -352,6 +411,9 @@ static int i386_limit_check(i386_state *cpustate, int seg, UINT32 offset);
|
||||
#define SetSZPF16(x) {cpustate->ZF = ((UINT16)(x)==0); cpustate->SF = ((x)&0x8000) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; }
|
||||
#define SetSZPF32(x) {cpustate->ZF = ((UINT32)(x)==0); cpustate->SF = ((x)&0x80000000) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; }
|
||||
|
||||
#define MMX(n) cpustate->fpu_reg[(n)].i
|
||||
#define XMM(n) cpustate->sse_reg[(n)]
|
||||
|
||||
/***********************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
@ -542,6 +604,10 @@ INLINE UINT8 FETCH(i386_state *cpustate)
|
||||
}
|
||||
|
||||
value = cpustate->direct->read_decrypted_byte(address & cpustate->a20_mask);
|
||||
#ifdef DEBUG_MISSING_OPCODE
|
||||
cpustate->opcode_bytes[cpustate->opcode_bytes_length] = value;
|
||||
cpustate->opcode_bytes_length = (cpustate->opcode_bytes_length + 1) & 15;
|
||||
#endif
|
||||
cpustate->eip++;
|
||||
cpustate->pc++;
|
||||
return value;
|
||||
|
@ -1,5 +1,29 @@
|
||||
// Pentium+ specific opcodes
|
||||
|
||||
/* return the single precision floating point number represented by the 32 bit value */
|
||||
INLINE float FPU_INT32_SINGLE(UINT32 value)
|
||||
{
|
||||
float v;
|
||||
|
||||
v=*((float *)&value);
|
||||
return v;
|
||||
}
|
||||
|
||||
INLINE UINT32 FPU_SINGLE_INT32(X87_REG value)
|
||||
{
|
||||
float fs=(float)value.f;
|
||||
UINT32 v;
|
||||
|
||||
v=*((UINT32 *)(&fs));
|
||||
return v;
|
||||
}
|
||||
|
||||
INLINE void MMXPROLOG(i386_state *cpustate)
|
||||
{
|
||||
//cpustate->x87_sw &= ~(X87_SW_TOP_MASK << X87_SW_TOP_SHIFT); // top = 0
|
||||
cpustate->x87_tw = 0; // tag word = 0
|
||||
}
|
||||
|
||||
static void PENTIUMOP(rdmsr)(i386_state *cpustate) // Opcode 0x0f 32
|
||||
{
|
||||
UINT64 data;
|
||||
@ -53,7 +77,7 @@ static void PENTIUMOP(cmpxchg8b_m64)(i386_state *cpustate) // Opcode 0x0f c7
|
||||
if( modm >= 0xc0 ) {
|
||||
fatalerror("pentium: cmpxchg8b_m64 - invalid modm");
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modm,0);
|
||||
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);
|
||||
@ -71,12 +95,45 @@ static void PENTIUMOP(cmpxchg8b_m64)(i386_state *cpustate) // Opcode 0x0f c7
|
||||
}
|
||||
}
|
||||
|
||||
static void PENTIUMOP(sse_group0fae)(i386_state *cpustate) // Opcode 0x0f ae
|
||||
INLINE void READXMM(i386_state *cpustate,UINT32 ea,XMM_REG &r)
|
||||
{
|
||||
r.q[0]=READ64(cpustate, ea);
|
||||
r.q[1]=READ64(cpustate, ea+8);
|
||||
}
|
||||
INLINE void WRITEXMM(i386_state *cpustate,UINT32 ea,XMM_REG &r)
|
||||
{
|
||||
WRITE64(cpustate, ea, r.q[0]);
|
||||
WRITE64(cpustate, ea+8, r.q[1]);
|
||||
}
|
||||
|
||||
static void SSEOP(sse_group0fae)(i386_state *cpustate) // Opcode 0f ae
|
||||
{
|
||||
UINT8 modm = FETCH(cpustate);
|
||||
if( modm == 0xf8 ) {
|
||||
logerror("Unemulated SFENCE opcode called\n");
|
||||
CYCLES(cpustate,1); // sfence instruction
|
||||
} else if( modm == 0xf0 ) {
|
||||
CYCLES(cpustate,1); // mfence instruction
|
||||
} else if( modm == 0xe8 ) {
|
||||
CYCLES(cpustate,1); // lfence instruction
|
||||
} else if( modm < 0xc0 ) {
|
||||
UINT32 ea;
|
||||
switch ( (modm & 0x38) >> 3 )
|
||||
{
|
||||
case 2: // ldmxcsr m32
|
||||
ea = GetEA(cpustate, modm, 0);
|
||||
cpustate->mxcsr = READ32(cpustate, ea);
|
||||
break;
|
||||
case 3: // stmxcsr m32
|
||||
ea = GetEA(cpustate, modm, 0);
|
||||
WRITE32(cpustate, ea, cpustate->mxcsr);
|
||||
break;
|
||||
case 7: // clflush m8
|
||||
GetNonTranslatedEA(cpustate, modm, NULL);
|
||||
break;
|
||||
default:
|
||||
fatalerror("pentium: bad/unsupported 0f ae opcode");
|
||||
}
|
||||
} else {
|
||||
fatalerror("pentium: bad/unsupported 0f ae opcode");
|
||||
}
|
||||
@ -86,3 +143,117 @@ static void PENTIUMOP(ud2)(i386_state *cpustate) // Opcode 0x0f 0b
|
||||
{
|
||||
i386_trap(cpustate, 6, 0, 0);
|
||||
}
|
||||
|
||||
static void SSEOP(cvttss2si)(i386_state *cpustate) // Opcode f3 0f 2c
|
||||
{
|
||||
UINT32 src;
|
||||
UINT8 modrm = FETCH(cpustate); // get mordm byte
|
||||
if( modrm >= 0xc0 ) { // if bits 7-6 are 11 the source is a xmm register (low doubleword)
|
||||
src = XMM(modrm & 0x7).d[0^NATIVE_ENDIAN_VALUE_LE_BE(0,1)];
|
||||
} else { // otherwise is a memory address
|
||||
UINT32 ea = GetEA(cpustate, modrm, 0);
|
||||
src = READ32(cpustate, ea);
|
||||
}
|
||||
STORE_REG32(modrm, (INT32)FPU_INT32_SINGLE(src));
|
||||
// TODO
|
||||
CYCLES(cpustate,1); // TODO: correct cycle count
|
||||
}
|
||||
|
||||
static void SSEOP(movaps_r128_rm128)(i386_state *cpustate) // Opcode 0f 28
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
if( modrm >= 0xc0 ) {
|
||||
XMM((modrm >> 3) & 0x7) = XMM(modrm & 0x7);
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate, modrm, 0);
|
||||
READXMM(cpustate, ea, XMM((modrm >> 3) & 0x7));
|
||||
}
|
||||
}
|
||||
|
||||
static void SSEOP(movaps_rm128_r128)(i386_state *cpustate) // Opcode 0f 29
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
if( modrm >= 0xc0 ) {
|
||||
XMM(modrm & 0x7) = XMM((modrm >> 3) & 0x7);
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate, modrm, 0);
|
||||
WRITEXMM(cpustate, ea, XMM((modrm >> 3) & 0x7));
|
||||
}
|
||||
}
|
||||
|
||||
static void SSEOP(addps)(i386_state *cpustate) // Opcode 0f 58
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
if( modrm >= 0xc0 ) {
|
||||
XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] + XMM(modrm & 0x7).f[0];
|
||||
XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] + XMM(modrm & 0x7).f[1];
|
||||
XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] + XMM(modrm & 0x7).f[2];
|
||||
XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] + XMM(modrm & 0x7).f[3];
|
||||
} else {
|
||||
XMM_REG src;
|
||||
UINT32 ea = GetEA(cpustate, modrm, 0);
|
||||
READXMM(cpustate, ea, src);
|
||||
XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] + src.f[0];
|
||||
XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] + src.f[1];
|
||||
XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] + src.f[2];
|
||||
XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] + src.f[3];
|
||||
}
|
||||
}
|
||||
|
||||
static void SSEOP(mulps)(i386_state *cpustate) // Opcode 0f 59
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
if( modrm >= 0xc0 ) {
|
||||
XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] * XMM(modrm & 0x7).f[0];
|
||||
XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] * XMM(modrm & 0x7).f[1];
|
||||
XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] * XMM(modrm & 0x7).f[2];
|
||||
XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] * XMM(modrm & 0x7).f[3];
|
||||
} else {
|
||||
XMM_REG src;
|
||||
UINT32 ea = GetEA(cpustate, modrm, 0);
|
||||
READXMM(cpustate, ea, src);
|
||||
XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] * src.f[0];
|
||||
XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] * src.f[1];
|
||||
XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] * src.f[2];
|
||||
XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] * src.f[3];
|
||||
}
|
||||
}
|
||||
|
||||
static void SSEOP(shufps)(i386_state *cpustate) // Opcode 0f 67
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
UINT8 sel = FETCH(cpustate);
|
||||
int m1,m2,m3,m4;
|
||||
int s,d;
|
||||
m1=sel & 3;
|
||||
m2=(sel >> 2) & 3;
|
||||
m3=(sel >> 4) & 3;
|
||||
m4=(sel >> 6) & 3;
|
||||
s=modrm & 0x7;
|
||||
d=(modrm >> 3) & 0x7;
|
||||
if( modrm >= 0xc0 ) {
|
||||
UINT32 t;
|
||||
t=XMM(d).d[m1];
|
||||
XMM(d).d[1]=XMM(d).d[m2];
|
||||
XMM(d).d[0]=t;
|
||||
XMM(d).d[2]=XMM(s).d[m3];
|
||||
XMM(d).d[3]=XMM(s).d[m4];
|
||||
} else {
|
||||
UINT32 t;
|
||||
XMM_REG src;
|
||||
UINT32 ea = GetEA(cpustate, modrm, 0);
|
||||
READXMM(cpustate, ea, src);
|
||||
t=XMM(d).d[m1];
|
||||
XMM(d).d[1]=XMM(d).d[m2];
|
||||
XMM(d).d[0]=t;
|
||||
XMM(d).d[2]=src.d[m3];
|
||||
XMM(d).d[3]=src.d[m4];
|
||||
}
|
||||
}
|
||||
|
||||
static void MMXOP(emms)(i386_state *cpustate) // Opcode 0f 77
|
||||
{
|
||||
cpustate->x87_tw = 0xffff; // tag word = 0xffff
|
||||
// TODO
|
||||
CYCLES(cpustate,1); // TODO: correct cycle count
|
||||
}
|
||||
|
@ -380,7 +380,7 @@ static floatx80 x87_sub(i386_state *cpustate, floatx80 a, floatx80 b)
|
||||
{
|
||||
float64 a64 = floatx80_to_float64(a);
|
||||
float64 b64 = floatx80_to_float64(b);
|
||||
result = float64_to_floatx80(float32_sub(a64, b64));
|
||||
result = float64_to_floatx80(float64_sub(a64, b64));
|
||||
break;
|
||||
}
|
||||
case X87_CW_PC_EXTEND:
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user