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:
Angelo Salese 2012-07-05 08:34:53 +00:00
parent c2a46ad456
commit 58a33d8b36
7 changed files with 1095 additions and 80 deletions

View File

@ -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];

View File

@ -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);
}

View File

@ -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), }
};

View File

@ -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;

View File

@ -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
}

View File

@ -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