Pointer-ified the i386.

This commit is contained in:
Aaron Giles 2008-12-10 05:14:09 +00:00
parent 129c08982e
commit 36d63663d3
9 changed files with 4550 additions and 4542 deletions

File diff suppressed because it is too large Load Diff

View File

@ -208,7 +208,9 @@ typedef union {
double f; double f;
} X87_REG; } X87_REG;
typedef struct { typedef struct _i386_state i386_state;
struct _i386_state
{
I386_GPR reg; I386_GPR reg;
I386_SREG sreg[6]; I386_SREG sreg[6];
UINT32 eip; UINT32 eip;
@ -271,45 +273,42 @@ typedef struct {
UINT16 fpu_opcode; UINT16 fpu_opcode;
int fpu_top; int fpu_top;
void (*opcode_table1_16[256])(void); void (*opcode_table1_16[256])(i386_state *cpustate);
void (*opcode_table1_32[256])(void); void (*opcode_table1_32[256])(i386_state *cpustate);
void (*opcode_table2_16[256])(void); void (*opcode_table2_16[256])(i386_state *cpustate);
void (*opcode_table2_32[256])(void); void (*opcode_table2_32[256])(i386_state *cpustate);
UINT8 *cycle_table_pm; UINT8 *cycle_table_pm;
UINT8 *cycle_table_rm; UINT8 *cycle_table_rm;
} I386_REGS; };
static I386_REGS I;
extern int i386_parity_table[256]; extern int i386_parity_table[256];
#define PROTECTED_MODE (I.cr[0] & 0x1) #define PROTECTED_MODE (cpustate->cr[0] & 0x1)
#define STACK_32BIT (I.sreg[SS].d) #define STACK_32BIT (cpustate->sreg[SS].d)
#define V8086_MODE (I.eflags & 0x00020000) #define V8086_MODE (cpustate->eflags & 0x00020000)
#define SetOF_Add32(r,s,d) (I.OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x80000000) ? 1: 0) #define SetOF_Add32(r,s,d) (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x80000000) ? 1: 0)
#define SetOF_Add16(r,s,d) (I.OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x8000) ? 1 : 0) #define SetOF_Add16(r,s,d) (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x8000) ? 1 : 0)
#define SetOF_Add8(r,s,d) (I.OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x80) ? 1 : 0) #define SetOF_Add8(r,s,d) (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x80) ? 1 : 0)
#define SetOF_Sub32(r,s,d) (I.OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x80000000) ? 1 : 0) #define SetOF_Sub32(r,s,d) (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x80000000) ? 1 : 0)
#define SetOF_Sub16(r,s,d) (I.OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x8000) ? 1 : 0) #define SetOF_Sub16(r,s,d) (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x8000) ? 1 : 0)
#define SetOF_Sub8(r,s,d) (I.OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x80) ? 1 : 0) #define SetOF_Sub8(r,s,d) (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x80) ? 1 : 0)
#define SetCF8(x) {I.CF = ((x) & 0x100) ? 1 : 0; } #define SetCF8(x) {cpustate->CF = ((x) & 0x100) ? 1 : 0; }
#define SetCF16(x) {I.CF = ((x) & 0x10000) ? 1 : 0; } #define SetCF16(x) {cpustate->CF = ((x) & 0x10000) ? 1 : 0; }
#define SetCF32(x) {I.CF = ((x) & (((UINT64)1) << 32)) ? 1 : 0; } #define SetCF32(x) {cpustate->CF = ((x) & (((UINT64)1) << 32)) ? 1 : 0; }
#define SetSF(x) (I.SF = (x)) #define SetSF(x) (cpustate->SF = (x))
#define SetZF(x) (I.ZF = (x)) #define SetZF(x) (cpustate->ZF = (x))
#define SetAF(x,y,z) (I.AF = (((x) ^ ((y) ^ (z))) & 0x10) ? 1 : 0) #define SetAF(x,y,z) (cpustate->AF = (((x) ^ ((y) ^ (z))) & 0x10) ? 1 : 0)
#define SetPF(x) (I.PF = i386_parity_table[(x) & 0xFF]) #define SetPF(x) (cpustate->PF = i386_parity_table[(x) & 0xFF])
#define SetSZPF8(x) {I.ZF = ((UINT8)(x)==0); I.SF = ((x)&0x80) ? 1 : 0; I.PF = i386_parity_table[x & 0xFF]; } #define SetSZPF8(x) {cpustate->ZF = ((UINT8)(x)==0); cpustate->SF = ((x)&0x80) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; }
#define SetSZPF16(x) {I.ZF = ((UINT16)(x)==0); I.SF = ((x)&0x8000) ? 1 : 0; I.PF = i386_parity_table[x & 0xFF]; } #define SetSZPF16(x) {cpustate->ZF = ((UINT16)(x)==0); cpustate->SF = ((x)&0x8000) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; }
#define SetSZPF32(x) {I.ZF = ((UINT32)(x)==0); I.SF = ((x)&0x80000000) ? 1 : 0; I.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]; }
/***********************************************************************************/ /***********************************************************************************/
@ -328,9 +327,9 @@ typedef struct {
extern MODRM_TABLE i386_MODRM_table[256]; extern MODRM_TABLE i386_MODRM_table[256];
#define REG8(x) (I.reg.b[x]) #define REG8(x) (cpustate->reg.b[x])
#define REG16(x) (I.reg.w[x]) #define REG16(x) (cpustate->reg.w[x])
#define REG32(x) (I.reg.d[x]) #define REG32(x) (cpustate->reg.d[x])
#define LOAD_REG8(x) (REG8(i386_MODRM_table[x].reg.b)) #define LOAD_REG8(x) (REG8(i386_MODRM_table[x].reg.b))
#define LOAD_REG16(x) (REG16(i386_MODRM_table[x].reg.w)) #define LOAD_REG16(x) (REG16(i386_MODRM_table[x].reg.w))
@ -348,341 +347,341 @@ extern MODRM_TABLE i386_MODRM_table[256];
/***********************************************************************************/ /***********************************************************************************/
INLINE UINT32 i386_translate(int segment, UINT32 ip) INLINE UINT32 i386_translate(i386_state *cpustate, int segment, UINT32 ip)
{ {
// TODO: segment limit // TODO: segment limit
return I.sreg[segment].base + ip; return cpustate->sreg[segment].base + ip;
} }
INLINE int translate_address(UINT32 *address) INLINE int translate_address(i386_state *cpustate, UINT32 *address)
{ {
UINT32 a = *address; UINT32 a = *address;
UINT32 pdbr = I.cr[3] & 0xfffff000; UINT32 pdbr = cpustate->cr[3] & 0xfffff000;
UINT32 directory = (a >> 22) & 0x3ff; UINT32 directory = (a >> 22) & 0x3ff;
UINT32 table = (a >> 12) & 0x3ff; UINT32 table = (a >> 12) & 0x3ff;
UINT32 offset = a & 0xfff; UINT32 offset = a & 0xfff;
// TODO: 4MB pages // TODO: 4MB pages
UINT32 page_dir = memory_read_dword_32le(I.program, pdbr + directory * 4); UINT32 page_dir = memory_read_dword_32le(cpustate->program, pdbr + directory * 4);
UINT32 page_entry = memory_read_dword_32le(I.program, (page_dir & 0xfffff000) + (table * 4)); UINT32 page_entry = memory_read_dword_32le(cpustate->program, (page_dir & 0xfffff000) + (table * 4));
*address = (page_entry & 0xfffff000) | offset; *address = (page_entry & 0xfffff000) | offset;
return 1; return 1;
} }
INLINE void CHANGE_PC(UINT32 pc) INLINE void CHANGE_PC(i386_state *cpustate, UINT32 pc)
{ {
UINT32 address; UINT32 address;
I.pc = i386_translate( CS, pc ); cpustate->pc = i386_translate(cpustate, CS, pc );
address = I.pc; address = cpustate->pc;
if (I.cr[0] & 0x80000000) // page translation enabled if (cpustate->cr[0] & 0x80000000) // page translation enabled
{ {
translate_address(&address); translate_address(cpustate,&address);
} }
} }
INLINE void NEAR_BRANCH(INT32 offs) INLINE void NEAR_BRANCH(i386_state *cpustate, INT32 offs)
{ {
UINT32 address; UINT32 address;
/* TODO: limit */ /* TODO: limit */
I.eip += offs; cpustate->eip += offs;
I.pc += offs; cpustate->pc += offs;
address = I.pc; address = cpustate->pc;
if (I.cr[0] & 0x80000000) // page translation enabled if (cpustate->cr[0] & 0x80000000) // page translation enabled
{ {
translate_address(&address); translate_address(cpustate,&address);
} }
} }
INLINE UINT8 FETCH(void) INLINE UINT8 FETCH(i386_state *cpustate)
{ {
UINT8 value; UINT8 value;
UINT32 address = I.pc; UINT32 address = cpustate->pc;
if (I.cr[0] & 0x80000000) // page translation enabled if (cpustate->cr[0] & 0x80000000) // page translation enabled
{ {
translate_address(&address); translate_address(cpustate,&address);
} }
value = memory_decrypted_read_byte(I.program, address & I.a20_mask); value = memory_decrypted_read_byte(cpustate->program, address & cpustate->a20_mask);
I.eip++; cpustate->eip++;
I.pc++; cpustate->pc++;
return value; return value;
} }
INLINE UINT16 FETCH16(void) INLINE UINT16 FETCH16(i386_state *cpustate)
{ {
UINT16 value; UINT16 value;
UINT32 address = I.pc; UINT32 address = cpustate->pc;
if (I.cr[0] & 0x80000000) // page translation enabled if (cpustate->cr[0] & 0x80000000) // page translation enabled
{ {
translate_address(&address); translate_address(cpustate,&address);
} }
if( address & 0x1 ) { /* Unaligned read */ if( address & 0x1 ) { /* Unaligned read */
address &= I.a20_mask; address &= cpustate->a20_mask;
value = (memory_decrypted_read_byte(I.program, address+0) << 0) | value = (memory_decrypted_read_byte(cpustate->program, address+0) << 0) |
(memory_decrypted_read_byte(I.program, address+1) << 8); (memory_decrypted_read_byte(cpustate->program, address+1) << 8);
} else { } else {
address &= I.a20_mask; address &= cpustate->a20_mask;
value = memory_decrypted_read_word(I.program, address); value = memory_decrypted_read_word(cpustate->program, address);
} }
I.eip += 2; cpustate->eip += 2;
I.pc += 2; cpustate->pc += 2;
return value; return value;
} }
INLINE UINT32 FETCH32(void) INLINE UINT32 FETCH32(i386_state *cpustate)
{ {
UINT32 value; UINT32 value;
UINT32 address = I.pc; UINT32 address = cpustate->pc;
if (I.cr[0] & 0x80000000) // page translation enabled if (cpustate->cr[0] & 0x80000000) // page translation enabled
{ {
translate_address(&address); translate_address(cpustate,&address);
} }
if( I.pc & 0x3 ) { /* Unaligned read */ if( cpustate->pc & 0x3 ) { /* Unaligned read */
address &= I.a20_mask; address &= cpustate->a20_mask;
value = (memory_decrypted_read_byte(I.program, address+0) << 0) | value = (memory_decrypted_read_byte(cpustate->program, address+0) << 0) |
(memory_decrypted_read_byte(I.program, address+1) << 8) | (memory_decrypted_read_byte(cpustate->program, address+1) << 8) |
(memory_decrypted_read_byte(I.program, address+2) << 16) | (memory_decrypted_read_byte(cpustate->program, address+2) << 16) |
(memory_decrypted_read_byte(I.program, address+3) << 24); (memory_decrypted_read_byte(cpustate->program, address+3) << 24);
} else { } else {
address &= I.a20_mask; address &= cpustate->a20_mask;
value = memory_decrypted_read_dword(I.program, address); value = memory_decrypted_read_dword(cpustate->program, address);
} }
I.eip += 4; cpustate->eip += 4;
I.pc += 4; cpustate->pc += 4;
return value; return value;
} }
INLINE UINT8 READ8(UINT32 ea) INLINE UINT8 READ8(i386_state *cpustate,UINT32 ea)
{ {
UINT32 address = ea; UINT32 address = ea;
if (I.cr[0] & 0x80000000) // page translation enabled if (cpustate->cr[0] & 0x80000000) // page translation enabled
{ {
translate_address(&address); translate_address(cpustate,&address);
} }
address &= I.a20_mask; address &= cpustate->a20_mask;
return memory_read_byte_32le(I.program, address); return memory_read_byte_32le(cpustate->program, address);
} }
INLINE UINT16 READ16(UINT32 ea) INLINE UINT16 READ16(i386_state *cpustate,UINT32 ea)
{ {
UINT16 value; UINT16 value;
UINT32 address = ea; UINT32 address = ea;
if (I.cr[0] & 0x80000000) // page translation enabled if (cpustate->cr[0] & 0x80000000) // page translation enabled
{ {
translate_address(&address); translate_address(cpustate,&address);
} }
address &= I.a20_mask; address &= cpustate->a20_mask;
if( ea & 0x1 ) { /* Unaligned read */ if( ea & 0x1 ) { /* Unaligned read */
value = (memory_read_byte_32le( I.program, address+0 ) << 0) | value = (memory_read_byte_32le( cpustate->program, address+0 ) << 0) |
(memory_read_byte_32le( I.program, address+1 ) << 8); (memory_read_byte_32le( cpustate->program, address+1 ) << 8);
} else { } else {
value = memory_read_word_32le( I.program, address ); value = memory_read_word_32le( cpustate->program, address );
} }
return value; return value;
} }
INLINE UINT32 READ32(UINT32 ea) INLINE UINT32 READ32(i386_state *cpustate,UINT32 ea)
{ {
UINT32 value; UINT32 value;
UINT32 address = ea; UINT32 address = ea;
if (I.cr[0] & 0x80000000) // page translation enabled if (cpustate->cr[0] & 0x80000000) // page translation enabled
{ {
translate_address(&address); translate_address(cpustate,&address);
} }
address &= I.a20_mask; address &= cpustate->a20_mask;
if( ea & 0x3 ) { /* Unaligned read */ if( ea & 0x3 ) { /* Unaligned read */
value = (memory_read_byte_32le( I.program, address+0 ) << 0) | value = (memory_read_byte_32le( cpustate->program, address+0 ) << 0) |
(memory_read_byte_32le( I.program, address+1 ) << 8) | (memory_read_byte_32le( cpustate->program, address+1 ) << 8) |
(memory_read_byte_32le( I.program, address+2 ) << 16) | (memory_read_byte_32le( cpustate->program, address+2 ) << 16) |
(memory_read_byte_32le( I.program, address+3 ) << 24); (memory_read_byte_32le( cpustate->program, address+3 ) << 24);
} else { } else {
value = memory_read_dword_32le( I.program, address ); value = memory_read_dword_32le( cpustate->program, address );
} }
return value; return value;
} }
INLINE UINT64 READ64(UINT32 ea) INLINE UINT64 READ64(i386_state *cpustate,UINT32 ea)
{ {
UINT64 value; UINT64 value;
UINT32 address = ea; UINT32 address = ea;
if (I.cr[0] & 0x80000000) // page translation enabled if (cpustate->cr[0] & 0x80000000) // page translation enabled
{ {
translate_address(&address); translate_address(cpustate,&address);
} }
address &= I.a20_mask; address &= cpustate->a20_mask;
if( ea & 0x7 ) { /* Unaligned read */ if( ea & 0x7 ) { /* Unaligned read */
value = (((UINT64) memory_read_byte_32le( I.program, address+0 )) << 0) | value = (((UINT64) memory_read_byte_32le( cpustate->program, address+0 )) << 0) |
(((UINT64) memory_read_byte_32le( I.program, address+1 )) << 8) | (((UINT64) memory_read_byte_32le( cpustate->program, address+1 )) << 8) |
(((UINT64) memory_read_byte_32le( I.program, address+2 )) << 16) | (((UINT64) memory_read_byte_32le( cpustate->program, address+2 )) << 16) |
(((UINT64) memory_read_byte_32le( I.program, address+3 )) << 24) | (((UINT64) memory_read_byte_32le( cpustate->program, address+3 )) << 24) |
(((UINT64) memory_read_byte_32le( I.program, address+4 )) << 32) | (((UINT64) memory_read_byte_32le( cpustate->program, address+4 )) << 32) |
(((UINT64) memory_read_byte_32le( I.program, address+5 )) << 40) | (((UINT64) memory_read_byte_32le( cpustate->program, address+5 )) << 40) |
(((UINT64) memory_read_byte_32le( I.program, address+6 )) << 48) | (((UINT64) memory_read_byte_32le( cpustate->program, address+6 )) << 48) |
(((UINT64) memory_read_byte_32le( I.program, address+7 )) << 56); (((UINT64) memory_read_byte_32le( cpustate->program, address+7 )) << 56);
} else { } else {
value = (((UINT64) memory_read_dword_32le( I.program, address+0 )) << 0) | value = (((UINT64) memory_read_dword_32le( cpustate->program, address+0 )) << 0) |
(((UINT64) memory_read_dword_32le( I.program, address+4 )) << 32); (((UINT64) memory_read_dword_32le( cpustate->program, address+4 )) << 32);
} }
return value; return value;
} }
INLINE void WRITE8(UINT32 ea, UINT8 value) INLINE void WRITE8(i386_state *cpustate,UINT32 ea, UINT8 value)
{ {
UINT32 address = ea; UINT32 address = ea;
if (I.cr[0] & 0x80000000) // page translation enabled if (cpustate->cr[0] & 0x80000000) // page translation enabled
{ {
translate_address(&address); translate_address(cpustate,&address);
} }
address &= I.a20_mask; address &= cpustate->a20_mask;
memory_write_byte_32le(I.program, address, value); memory_write_byte_32le(cpustate->program, address, value);
} }
INLINE void WRITE16(UINT32 ea, UINT16 value) INLINE void WRITE16(i386_state *cpustate,UINT32 ea, UINT16 value)
{ {
UINT32 address = ea; UINT32 address = ea;
if (I.cr[0] & 0x80000000) // page translation enabled if (cpustate->cr[0] & 0x80000000) // page translation enabled
{ {
translate_address(&address); translate_address(cpustate,&address);
} }
address &= I.a20_mask; address &= cpustate->a20_mask;
if( ea & 0x1 ) { /* Unaligned write */ if( ea & 0x1 ) { /* Unaligned write */
memory_write_byte_32le( I.program, address+0, value & 0xff ); memory_write_byte_32le( cpustate->program, address+0, value & 0xff );
memory_write_byte_32le( I.program, address+1, (value >> 8) & 0xff ); memory_write_byte_32le( cpustate->program, address+1, (value >> 8) & 0xff );
} else { } else {
memory_write_word_32le(I.program, address, value); memory_write_word_32le(cpustate->program, address, value);
} }
} }
INLINE void WRITE32(UINT32 ea, UINT32 value) INLINE void WRITE32(i386_state *cpustate,UINT32 ea, UINT32 value)
{ {
UINT32 address = ea; UINT32 address = ea;
if (I.cr[0] & 0x80000000) // page translation enabled if (cpustate->cr[0] & 0x80000000) // page translation enabled
{ {
translate_address(&address); translate_address(cpustate,&address);
} }
ea &= I.a20_mask; ea &= cpustate->a20_mask;
if( ea & 0x3 ) { /* Unaligned write */ if( ea & 0x3 ) { /* Unaligned write */
memory_write_byte_32le( I.program, address+0, value & 0xff ); memory_write_byte_32le( cpustate->program, address+0, value & 0xff );
memory_write_byte_32le( I.program, address+1, (value >> 8) & 0xff ); memory_write_byte_32le( cpustate->program, address+1, (value >> 8) & 0xff );
memory_write_byte_32le( I.program, address+2, (value >> 16) & 0xff ); memory_write_byte_32le( cpustate->program, address+2, (value >> 16) & 0xff );
memory_write_byte_32le( I.program, address+3, (value >> 24) & 0xff ); memory_write_byte_32le( cpustate->program, address+3, (value >> 24) & 0xff );
} else { } else {
memory_write_dword_32le(I.program, address, value); memory_write_dword_32le(cpustate->program, address, value);
} }
} }
INLINE void WRITE64(UINT32 ea, UINT64 value) INLINE void WRITE64(i386_state *cpustate,UINT32 ea, UINT64 value)
{ {
UINT32 address = ea; UINT32 address = ea;
if (I.cr[0] & 0x80000000) // page translation enabled if (cpustate->cr[0] & 0x80000000) // page translation enabled
{ {
translate_address(&address); translate_address(cpustate,&address);
} }
ea &= I.a20_mask; ea &= cpustate->a20_mask;
if( ea & 0x7 ) { /* Unaligned write */ if( ea & 0x7 ) { /* Unaligned write */
memory_write_byte_32le( I.program, address+0, value & 0xff ); memory_write_byte_32le( cpustate->program, address+0, value & 0xff );
memory_write_byte_32le( I.program, address+1, (value >> 8) & 0xff ); memory_write_byte_32le( cpustate->program, address+1, (value >> 8) & 0xff );
memory_write_byte_32le( I.program, address+2, (value >> 16) & 0xff ); memory_write_byte_32le( cpustate->program, address+2, (value >> 16) & 0xff );
memory_write_byte_32le( I.program, address+3, (value >> 24) & 0xff ); memory_write_byte_32le( cpustate->program, address+3, (value >> 24) & 0xff );
memory_write_byte_32le( I.program, address+4, (value >> 32) & 0xff ); memory_write_byte_32le( cpustate->program, address+4, (value >> 32) & 0xff );
memory_write_byte_32le( I.program, address+5, (value >> 40) & 0xff ); memory_write_byte_32le( cpustate->program, address+5, (value >> 40) & 0xff );
memory_write_byte_32le( I.program, address+6, (value >> 48) & 0xff ); memory_write_byte_32le( cpustate->program, address+6, (value >> 48) & 0xff );
memory_write_byte_32le( I.program, address+7, (value >> 56) & 0xff ); memory_write_byte_32le( cpustate->program, address+7, (value >> 56) & 0xff );
} else { } else {
memory_write_dword_32le(I.program, address+0, value & 0xffffffff); memory_write_dword_32le(cpustate->program, address+0, value & 0xffffffff);
memory_write_dword_32le(I.program, address+4, (value >> 32) & 0xffffffff); memory_write_dword_32le(cpustate->program, address+4, (value >> 32) & 0xffffffff);
} }
} }
/***********************************************************************************/ /***********************************************************************************/
INLINE UINT8 OR8(UINT8 dst, UINT8 src) INLINE UINT8 OR8(i386_state *cpustate,UINT8 dst, UINT8 src)
{ {
UINT8 res = dst | src; UINT8 res = dst | src;
I.CF = I.OF = 0; cpustate->CF = cpustate->OF = 0;
SetSZPF8(res); SetSZPF8(res);
return res; return res;
} }
INLINE UINT16 OR16(UINT16 dst, UINT16 src) INLINE UINT16 OR16(i386_state *cpustate,UINT16 dst, UINT16 src)
{ {
UINT16 res = dst | src; UINT16 res = dst | src;
I.CF = I.OF = 0; cpustate->CF = cpustate->OF = 0;
SetSZPF16(res); SetSZPF16(res);
return res; return res;
} }
INLINE UINT32 OR32(UINT32 dst, UINT32 src) INLINE UINT32 OR32(i386_state *cpustate,UINT32 dst, UINT32 src)
{ {
UINT32 res = dst | src; UINT32 res = dst | src;
I.CF = I.OF = 0; cpustate->CF = cpustate->OF = 0;
SetSZPF32(res); SetSZPF32(res);
return res; return res;
} }
INLINE UINT8 AND8(UINT8 dst, UINT8 src) INLINE UINT8 AND8(i386_state *cpustate,UINT8 dst, UINT8 src)
{ {
UINT8 res = dst & src; UINT8 res = dst & src;
I.CF = I.OF = 0; cpustate->CF = cpustate->OF = 0;
SetSZPF8(res); SetSZPF8(res);
return res; return res;
} }
INLINE UINT16 AND16(UINT16 dst, UINT16 src) INLINE UINT16 AND16(i386_state *cpustate,UINT16 dst, UINT16 src)
{ {
UINT16 res = dst & src; UINT16 res = dst & src;
I.CF = I.OF = 0; cpustate->CF = cpustate->OF = 0;
SetSZPF16(res); SetSZPF16(res);
return res; return res;
} }
INLINE UINT32 AND32(UINT32 dst, UINT32 src) INLINE UINT32 AND32(i386_state *cpustate,UINT32 dst, UINT32 src)
{ {
UINT32 res = dst & src; UINT32 res = dst & src;
I.CF = I.OF = 0; cpustate->CF = cpustate->OF = 0;
SetSZPF32(res); SetSZPF32(res);
return res; return res;
} }
INLINE UINT8 XOR8(UINT8 dst, UINT8 src) INLINE UINT8 XOR8(i386_state *cpustate,UINT8 dst, UINT8 src)
{ {
UINT8 res = dst ^ src; UINT8 res = dst ^ src;
I.CF = I.OF = 0; cpustate->CF = cpustate->OF = 0;
SetSZPF8(res); SetSZPF8(res);
return res; return res;
} }
INLINE UINT16 XOR16(UINT16 dst, UINT16 src) INLINE UINT16 XOR16(i386_state *cpustate,UINT16 dst, UINT16 src)
{ {
UINT16 res = dst ^ src; UINT16 res = dst ^ src;
I.CF = I.OF = 0; cpustate->CF = cpustate->OF = 0;
SetSZPF16(res); SetSZPF16(res);
return res; return res;
} }
INLINE UINT32 XOR32(UINT32 dst, UINT32 src) INLINE UINT32 XOR32(i386_state *cpustate,UINT32 dst, UINT32 src)
{ {
UINT32 res = dst ^ src; UINT32 res = dst ^ src;
I.CF = I.OF = 0; cpustate->CF = cpustate->OF = 0;
SetSZPF32(res); SetSZPF32(res);
return res; return res;
} }
INLINE UINT8 SUB8(UINT8 dst, UINT8 src) INLINE UINT8 SUB8(i386_state *cpustate,UINT8 dst, UINT8 src)
{ {
UINT16 res = (UINT16)dst - (UINT16)src; UINT16 res = (UINT16)dst - (UINT16)src;
SetCF8(res); SetCF8(res);
@ -691,7 +690,7 @@ INLINE UINT8 SUB8(UINT8 dst, UINT8 src)
SetSZPF8(res); SetSZPF8(res);
return (UINT8)res; return (UINT8)res;
} }
INLINE UINT16 SUB16(UINT16 dst, UINT16 src) INLINE UINT16 SUB16(i386_state *cpustate,UINT16 dst, UINT16 src)
{ {
UINT32 res = (UINT32)dst - (UINT32)src; UINT32 res = (UINT32)dst - (UINT32)src;
SetCF16(res); SetCF16(res);
@ -700,7 +699,7 @@ INLINE UINT16 SUB16(UINT16 dst, UINT16 src)
SetSZPF16(res); SetSZPF16(res);
return (UINT16)res; return (UINT16)res;
} }
INLINE UINT32 SUB32(UINT32 dst, UINT32 src) INLINE UINT32 SUB32(i386_state *cpustate,UINT32 dst, UINT32 src)
{ {
UINT64 res = (UINT64)dst - (UINT64)src; UINT64 res = (UINT64)dst - (UINT64)src;
SetCF32(res); SetCF32(res);
@ -710,7 +709,7 @@ INLINE UINT32 SUB32(UINT32 dst, UINT32 src)
return (UINT32)res; return (UINT32)res;
} }
INLINE UINT8 ADD8(UINT8 dst, UINT8 src) INLINE UINT8 ADD8(i386_state *cpustate,UINT8 dst, UINT8 src)
{ {
UINT16 res = (UINT16)dst + (UINT16)src; UINT16 res = (UINT16)dst + (UINT16)src;
SetCF8(res); SetCF8(res);
@ -719,7 +718,7 @@ INLINE UINT8 ADD8(UINT8 dst, UINT8 src)
SetSZPF8(res); SetSZPF8(res);
return (UINT8)res; return (UINT8)res;
} }
INLINE UINT16 ADD16(UINT16 dst, UINT16 src) INLINE UINT16 ADD16(i386_state *cpustate,UINT16 dst, UINT16 src)
{ {
UINT32 res = (UINT32)dst + (UINT32)src; UINT32 res = (UINT32)dst + (UINT32)src;
SetCF16(res); SetCF16(res);
@ -728,7 +727,7 @@ INLINE UINT16 ADD16(UINT16 dst, UINT16 src)
SetSZPF16(res); SetSZPF16(res);
return (UINT16)res; return (UINT16)res;
} }
INLINE UINT32 ADD32(UINT32 dst, UINT32 src) INLINE UINT32 ADD32(i386_state *cpustate,UINT32 dst, UINT32 src)
{ {
UINT64 res = (UINT64)dst + (UINT64)src; UINT64 res = (UINT64)dst + (UINT64)src;
SetCF32(res); SetCF32(res);
@ -738,7 +737,7 @@ INLINE UINT32 ADD32(UINT32 dst, UINT32 src)
return (UINT32)res; return (UINT32)res;
} }
INLINE UINT8 INC8(UINT8 dst) INLINE UINT8 INC8(i386_state *cpustate,UINT8 dst)
{ {
UINT16 res = (UINT16)dst + 1; UINT16 res = (UINT16)dst + 1;
SetOF_Add8(res,1,dst); SetOF_Add8(res,1,dst);
@ -746,7 +745,7 @@ INLINE UINT8 INC8(UINT8 dst)
SetSZPF8(res); SetSZPF8(res);
return (UINT8)res; return (UINT8)res;
} }
INLINE UINT16 INC16(UINT16 dst) INLINE UINT16 INC16(i386_state *cpustate,UINT16 dst)
{ {
UINT32 res = (UINT32)dst + 1; UINT32 res = (UINT32)dst + 1;
SetOF_Add16(res,1,dst); SetOF_Add16(res,1,dst);
@ -754,7 +753,7 @@ INLINE UINT16 INC16(UINT16 dst)
SetSZPF16(res); SetSZPF16(res);
return (UINT16)res; return (UINT16)res;
} }
INLINE UINT32 INC32(UINT32 dst) INLINE UINT32 INC32(i386_state *cpustate,UINT32 dst)
{ {
UINT64 res = (UINT64)dst + 1; UINT64 res = (UINT64)dst + 1;
SetOF_Add32(res,1,dst); SetOF_Add32(res,1,dst);
@ -763,7 +762,7 @@ INLINE UINT32 INC32(UINT32 dst)
return (UINT32)res; return (UINT32)res;
} }
INLINE UINT8 DEC8(UINT8 dst) INLINE UINT8 DEC8(i386_state *cpustate,UINT8 dst)
{ {
UINT16 res = (UINT16)dst - 1; UINT16 res = (UINT16)dst - 1;
SetOF_Sub8(res,1,dst); SetOF_Sub8(res,1,dst);
@ -771,7 +770,7 @@ INLINE UINT8 DEC8(UINT8 dst)
SetSZPF8(res); SetSZPF8(res);
return (UINT8)res; return (UINT8)res;
} }
INLINE UINT16 DEC16(UINT16 dst) INLINE UINT16 DEC16(i386_state *cpustate,UINT16 dst)
{ {
UINT32 res = (UINT32)dst - 1; UINT32 res = (UINT32)dst - 1;
SetOF_Sub16(res,1,dst); SetOF_Sub16(res,1,dst);
@ -779,7 +778,7 @@ INLINE UINT16 DEC16(UINT16 dst)
SetSZPF16(res); SetSZPF16(res);
return (UINT16)res; return (UINT16)res;
} }
INLINE UINT32 DEC32(UINT32 dst) INLINE UINT32 DEC32(i386_state *cpustate,UINT32 dst)
{ {
UINT64 res = (UINT64)dst - 1; UINT64 res = (UINT64)dst - 1;
SetOF_Sub32(res,1,dst); SetOF_Sub32(res,1,dst);
@ -790,112 +789,112 @@ INLINE UINT32 DEC32(UINT32 dst)
INLINE void PUSH16(UINT16 value) INLINE void PUSH16(i386_state *cpustate,UINT16 value)
{ {
UINT32 ea; UINT32 ea;
if( STACK_32BIT ) { if( STACK_32BIT ) {
REG32(ESP) -= 2; REG32(ESP) -= 2;
ea = i386_translate( SS, REG32(ESP) ); ea = i386_translate(cpustate, SS, REG32(ESP) );
WRITE16( ea, value ); WRITE16(cpustate, ea, value );
} else { } else {
REG16(SP) -= 2; REG16(SP) -= 2;
ea = i386_translate( SS, REG16(SP) ); ea = i386_translate(cpustate, SS, REG16(SP) );
WRITE16( ea, value ); WRITE16(cpustate, ea, value );
} }
} }
INLINE void PUSH32(UINT32 value) INLINE void PUSH32(i386_state *cpustate,UINT32 value)
{ {
UINT32 ea; UINT32 ea;
if( STACK_32BIT ) { if( STACK_32BIT ) {
REG32(ESP) -= 4; REG32(ESP) -= 4;
ea = i386_translate( SS, REG32(ESP) ); ea = i386_translate(cpustate, SS, REG32(ESP) );
WRITE32( ea, value ); WRITE32(cpustate, ea, value );
} else { } else {
REG16(SP) -= 4; REG16(SP) -= 4;
ea = i386_translate( SS, REG16(SP) ); ea = i386_translate(cpustate, SS, REG16(SP) );
WRITE32( ea, value ); WRITE32(cpustate, ea, value );
} }
} }
INLINE void PUSH8(UINT8 value) INLINE void PUSH8(i386_state *cpustate,UINT8 value)
{ {
if( I.operand_size ) { if( cpustate->operand_size ) {
PUSH32((INT32)(INT8)value); PUSH32(cpustate,(INT32)(INT8)value);
} else { } else {
PUSH16((INT16)(INT8)value); PUSH16(cpustate,(INT16)(INT8)value);
} }
} }
INLINE UINT8 POP8(void) INLINE UINT8 POP8(i386_state *cpustate)
{ {
UINT8 value; UINT8 value;
UINT32 ea; UINT32 ea;
if( STACK_32BIT ) { if( STACK_32BIT ) {
ea = i386_translate( SS, REG32(ESP) ); ea = i386_translate(cpustate, SS, REG32(ESP) );
value = READ8( ea ); value = READ8(cpustate, ea );
REG32(ESP) += 1; REG32(ESP) += 1;
} else { } else {
ea = i386_translate( SS, REG16(SP) ); ea = i386_translate(cpustate, SS, REG16(SP) );
value = READ8( ea ); value = READ8(cpustate, ea );
REG16(SP) += 1; REG16(SP) += 1;
} }
return value; return value;
} }
INLINE UINT16 POP16(void) INLINE UINT16 POP16(i386_state *cpustate)
{ {
UINT16 value; UINT16 value;
UINT32 ea; UINT32 ea;
if( STACK_32BIT ) { if( STACK_32BIT ) {
ea = i386_translate( SS, REG32(ESP) ); ea = i386_translate(cpustate, SS, REG32(ESP) );
value = READ16( ea ); value = READ16(cpustate, ea );
REG32(ESP) += 2; REG32(ESP) += 2;
} else { } else {
ea = i386_translate( SS, REG16(SP) ); ea = i386_translate(cpustate, SS, REG16(SP) );
value = READ16( ea ); value = READ16(cpustate, ea );
REG16(SP) += 2; REG16(SP) += 2;
} }
return value; return value;
} }
INLINE UINT32 POP32(void) INLINE UINT32 POP32(i386_state *cpustate)
{ {
UINT32 value; UINT32 value;
UINT32 ea; UINT32 ea;
if( STACK_32BIT ) { if( STACK_32BIT ) {
ea = i386_translate( SS, REG32(ESP) ); ea = i386_translate(cpustate, SS, REG32(ESP) );
value = READ32( ea ); value = READ32(cpustate, ea );
REG32(ESP) += 4; REG32(ESP) += 4;
} else { } else {
ea = i386_translate( SS, REG16(SP) ); ea = i386_translate(cpustate, SS, REG16(SP) );
value = READ32( ea ); value = READ32(cpustate, ea );
REG16(SP) += 4; REG16(SP) += 4;
} }
return value; return value;
} }
INLINE void BUMP_SI(int adjustment) INLINE void BUMP_SI(i386_state *cpustate,int adjustment)
{ {
if ( I.address_size ) if ( cpustate->address_size )
REG32(ESI) += ((I.DF) ? -adjustment : +adjustment); REG32(ESI) += ((cpustate->DF) ? -adjustment : +adjustment);
else else
REG16(SI) += ((I.DF) ? -adjustment : +adjustment); REG16(SI) += ((cpustate->DF) ? -adjustment : +adjustment);
} }
INLINE void BUMP_DI(int adjustment) INLINE void BUMP_DI(i386_state *cpustate,int adjustment)
{ {
if ( I.address_size ) if ( cpustate->address_size )
REG32(EDI) += ((I.DF) ? -adjustment : +adjustment); REG32(EDI) += ((cpustate->DF) ? -adjustment : +adjustment);
else else
REG16(DI) += ((I.DF) ? -adjustment : +adjustment); REG16(DI) += ((cpustate->DF) ? -adjustment : +adjustment);
} }
/***********************************************************************************/ /***********************************************************************************/
#define READPORT8(port) (memory_read_byte_32le(I.io, port)) #define READPORT8(port) (memory_read_byte_32le(cpustate->io, port))
#define READPORT16(port) (memory_read_word_32le(I.io, port)) #define READPORT16(port) (memory_read_word_32le(cpustate->io, port))
#define READPORT32(port) (memory_read_dword_32le(I.io, port)) #define READPORT32(port) (memory_read_dword_32le(cpustate->io, port))
#define WRITEPORT8(port, value) (memory_write_byte_32le(I.io, port, value)) #define WRITEPORT8(port, value) (memory_write_byte_32le(cpustate->io, port, value))
#define WRITEPORT16(port, value) (memory_write_word_32le(I.io, port, value)) #define WRITEPORT16(port, value) (memory_write_word_32le(cpustate->io, port, value))
#define WRITEPORT32(port, value) (memory_write_dword_32le(I.io, port, value)) #define WRITEPORT32(port, value) (memory_write_dword_32le(cpustate->io, port, value))
#endif /* __I386_H__ */ #endif /* __I386_H__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
typedef struct { typedef struct {
UINT8 opcode; UINT8 opcode;
UINT32 flags; UINT32 flags;
void (*handler16)(void); void (*handler16)(i386_state *cpustate);
void (*handler32)(void); void (*handler32)(i386_state *cpustate);
} X86_OPCODE; } X86_OPCODE;
#define OP_I386 0x1 #define OP_I386 0x1

View File

@ -1,199 +1,199 @@
// Intel 486+ specific opcodes // Intel 486+ specific opcodes
static void I486OP(cpuid)(void) // Opcode 0x0F A2 static void I486OP(cpuid)(i386_state *cpustate) // Opcode 0x0F A2
{ {
switch (REG32(EAX)) switch (REG32(EAX))
{ {
case 0: case 0:
{ {
REG32(EAX) = I.cpuid_max_input_value_eax; REG32(EAX) = cpustate->cpuid_max_input_value_eax;
REG32(EBX) = I.cpuid_id0; REG32(EBX) = cpustate->cpuid_id0;
REG32(ECX) = I.cpuid_id2; REG32(ECX) = cpustate->cpuid_id2;
REG32(EDX) = I.cpuid_id1; REG32(EDX) = cpustate->cpuid_id1;
CYCLES(CYCLES_CPUID); CYCLES(cpustate,CYCLES_CPUID);
break; break;
} }
case 1: case 1:
{ {
REG32(EAX) = I.cpu_version; REG32(EAX) = cpustate->cpu_version;
REG32(EDX) = I.feature_flags; REG32(EDX) = cpustate->feature_flags;
CYCLES(CYCLES_CPUID_EAX1); CYCLES(cpustate,CYCLES_CPUID_EAX1);
break; break;
} }
} }
} }
static void I486OP(invd)(void) // Opcode 0x0f 08 static void I486OP(invd)(i386_state *cpustate) // Opcode 0x0f 08
{ {
// Nothing to do ? // Nothing to do ?
CYCLES(CYCLES_INVD); CYCLES(cpustate,CYCLES_INVD);
} }
static void I486OP(wbinvd)(void) // Opcode 0x0f 09 static void I486OP(wbinvd)(i386_state *cpustate) // Opcode 0x0f 09
{ {
// Nothing to do ? // Nothing to do ?
} }
static void I486OP(cmpxchg_rm8_r8)(void) // Opcode 0x0f b0 static void I486OP(cmpxchg_rm8_r8)(i386_state *cpustate) // Opcode 0x0f b0
{ {
UINT8 modrm = FETCH(); UINT8 modrm = FETCH(cpustate);
if( modrm >= 0xc0 ) { if( modrm >= 0xc0 ) {
UINT8 dst = LOAD_RM8(modrm); UINT8 dst = LOAD_RM8(modrm);
UINT8 src = LOAD_REG8(modrm); UINT8 src = LOAD_REG8(modrm);
if( REG8(AL) == dst ) { if( REG8(AL) == dst ) {
STORE_RM8(modrm, src); STORE_RM8(modrm, src);
I.ZF = 1; cpustate->ZF = 1;
CYCLES(CYCLES_CMPXCHG_REG_REG_T); CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T);
} else { } else {
REG8(AL) = dst; REG8(AL) = dst;
I.ZF = 0; cpustate->ZF = 0;
CYCLES(CYCLES_CMPXCHG_REG_REG_F); CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F);
} }
} else { } else {
UINT32 ea = GetEA(modrm); UINT32 ea = GetEA(cpustate,modrm);
UINT8 dst = READ8(ea); UINT8 dst = READ8(cpustate,ea);
UINT8 src = LOAD_REG8(modrm); UINT8 src = LOAD_REG8(modrm);
if( REG8(AL) == dst ) { if( REG8(AL) == dst ) {
WRITE8(modrm, src); WRITE8(cpustate,modrm, src);
I.ZF = 1; cpustate->ZF = 1;
CYCLES(CYCLES_CMPXCHG_REG_MEM_T); CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
} else { } else {
REG8(AL) = dst; REG8(AL) = dst;
I.ZF = 0; cpustate->ZF = 0;
CYCLES(CYCLES_CMPXCHG_REG_MEM_F); CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
} }
} }
} }
static void I486OP(cmpxchg_rm16_r16)(void) // Opcode 0x0f b1 static void I486OP(cmpxchg_rm16_r16)(i386_state *cpustate) // Opcode 0x0f b1
{ {
UINT8 modrm = FETCH(); UINT8 modrm = FETCH(cpustate);
if( modrm >= 0xc0 ) { if( modrm >= 0xc0 ) {
UINT16 dst = LOAD_RM16(modrm); UINT16 dst = LOAD_RM16(modrm);
UINT16 src = LOAD_REG16(modrm); UINT16 src = LOAD_REG16(modrm);
if( REG16(AX) == dst ) { if( REG16(AX) == dst ) {
STORE_RM16(modrm, src); STORE_RM16(modrm, src);
I.ZF = 1; cpustate->ZF = 1;
CYCLES(CYCLES_CMPXCHG_REG_REG_T); CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T);
} else { } else {
REG16(AX) = dst; REG16(AX) = dst;
I.ZF = 0; cpustate->ZF = 0;
CYCLES(CYCLES_CMPXCHG_REG_REG_F); CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F);
} }
} else { } else {
UINT32 ea = GetEA(modrm); UINT32 ea = GetEA(cpustate,modrm);
UINT16 dst = READ16(ea); UINT16 dst = READ16(cpustate,ea);
UINT16 src = LOAD_REG16(modrm); UINT16 src = LOAD_REG16(modrm);
if( REG16(AX) == dst ) { if( REG16(AX) == dst ) {
WRITE16(modrm, src); WRITE16(cpustate,modrm, src);
I.ZF = 1; cpustate->ZF = 1;
CYCLES(CYCLES_CMPXCHG_REG_MEM_T); CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
} else { } else {
REG16(AX) = dst; REG16(AX) = dst;
I.ZF = 0; cpustate->ZF = 0;
CYCLES(CYCLES_CMPXCHG_REG_MEM_F); CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
} }
} }
} }
static void I486OP(cmpxchg_rm32_r32)(void) // Opcode 0x0f b1 static void I486OP(cmpxchg_rm32_r32)(i386_state *cpustate) // Opcode 0x0f b1
{ {
UINT8 modrm = FETCH(); UINT8 modrm = FETCH(cpustate);
if( modrm >= 0xc0 ) { if( modrm >= 0xc0 ) {
UINT32 dst = LOAD_RM32(modrm); UINT32 dst = LOAD_RM32(modrm);
UINT32 src = LOAD_REG32(modrm); UINT32 src = LOAD_REG32(modrm);
if( REG32(EAX) == dst ) { if( REG32(EAX) == dst ) {
STORE_RM32(modrm, src); STORE_RM32(modrm, src);
I.ZF = 1; cpustate->ZF = 1;
CYCLES(CYCLES_CMPXCHG_REG_REG_T); CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T);
} else { } else {
REG32(EAX) = dst; REG32(EAX) = dst;
I.ZF = 0; cpustate->ZF = 0;
CYCLES(CYCLES_CMPXCHG_REG_REG_F); CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F);
} }
} else { } else {
UINT32 ea = GetEA(modrm); UINT32 ea = GetEA(cpustate,modrm);
UINT32 dst = READ32(ea); UINT32 dst = READ32(cpustate,ea);
UINT32 src = LOAD_REG32(modrm); UINT32 src = LOAD_REG32(modrm);
if( REG32(EAX) == dst ) { if( REG32(EAX) == dst ) {
WRITE32(ea, src); WRITE32(cpustate,ea, src);
I.ZF = 1; cpustate->ZF = 1;
CYCLES(CYCLES_CMPXCHG_REG_MEM_T); CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
} else { } else {
REG32(EAX) = dst; REG32(EAX) = dst;
I.ZF = 0; cpustate->ZF = 0;
CYCLES(CYCLES_CMPXCHG_REG_MEM_F); CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
} }
} }
} }
static void I486OP(xadd_rm8_r8)(void) // Opcode 0x0f c0 static void I486OP(xadd_rm8_r8)(i386_state *cpustate) // Opcode 0x0f c0
{ {
UINT8 modrm = FETCH(); UINT8 modrm = FETCH(cpustate);
if( modrm >= 0xc0 ) { if( modrm >= 0xc0 ) {
UINT8 dst = LOAD_RM8(modrm); UINT8 dst = LOAD_RM8(modrm);
UINT8 src = LOAD_REG8(modrm); UINT8 src = LOAD_REG8(modrm);
STORE_RM16(modrm, dst + src); STORE_RM16(modrm, dst + src);
STORE_REG16(modrm, dst); STORE_REG16(modrm, dst);
CYCLES(CYCLES_XADD_REG_REG); CYCLES(cpustate,CYCLES_XADD_REG_REG);
} else { } else {
UINT32 ea = GetEA(modrm); UINT32 ea = GetEA(cpustate,modrm);
UINT8 dst = READ8(ea); UINT8 dst = READ8(cpustate,ea);
UINT8 src = LOAD_REG8(modrm); UINT8 src = LOAD_REG8(modrm);
WRITE8(ea, dst + src); WRITE8(cpustate,ea, dst + src);
STORE_REG8(modrm, dst); STORE_REG8(modrm, dst);
CYCLES(CYCLES_XADD_REG_MEM); CYCLES(cpustate,CYCLES_XADD_REG_MEM);
} }
} }
static void I486OP(xadd_rm16_r16)(void) // Opcode 0x0f c1 static void I486OP(xadd_rm16_r16)(i386_state *cpustate) // Opcode 0x0f c1
{ {
UINT8 modrm = FETCH(); UINT8 modrm = FETCH(cpustate);
if( modrm >= 0xc0 ) { if( modrm >= 0xc0 ) {
UINT16 dst = LOAD_RM16(modrm); UINT16 dst = LOAD_RM16(modrm);
UINT16 src = LOAD_REG16(modrm); UINT16 src = LOAD_REG16(modrm);
STORE_RM16(modrm, dst + src); STORE_RM16(modrm, dst + src);
STORE_REG16(modrm, dst); STORE_REG16(modrm, dst);
CYCLES(CYCLES_XADD_REG_REG); CYCLES(cpustate,CYCLES_XADD_REG_REG);
} else { } else {
UINT32 ea = GetEA(modrm); UINT32 ea = GetEA(cpustate,modrm);
UINT16 dst = READ16(ea); UINT16 dst = READ16(cpustate,ea);
UINT16 src = LOAD_REG16(modrm); UINT16 src = LOAD_REG16(modrm);
WRITE16(ea, dst + src); WRITE16(cpustate,ea, dst + src);
STORE_REG16(modrm, dst); STORE_REG16(modrm, dst);
CYCLES(CYCLES_XADD_REG_MEM); CYCLES(cpustate,CYCLES_XADD_REG_MEM);
} }
} }
static void I486OP(xadd_rm32_r32)(void) // Opcode 0x0f c1 static void I486OP(xadd_rm32_r32)(i386_state *cpustate) // Opcode 0x0f c1
{ {
UINT8 modrm = FETCH(); UINT8 modrm = FETCH(cpustate);
if( modrm >= 0xc0 ) { if( modrm >= 0xc0 ) {
UINT32 dst = LOAD_RM32(modrm); UINT32 dst = LOAD_RM32(modrm);
UINT32 src = LOAD_REG32(modrm); UINT32 src = LOAD_REG32(modrm);
STORE_RM32(modrm, dst + src); STORE_RM32(modrm, dst + src);
STORE_REG32(modrm, dst); STORE_REG32(modrm, dst);
CYCLES(CYCLES_XADD_REG_REG); CYCLES(cpustate,CYCLES_XADD_REG_REG);
} else { } else {
UINT32 ea = GetEA(modrm); UINT32 ea = GetEA(cpustate,modrm);
UINT32 dst = READ32(ea); UINT32 dst = READ32(cpustate,ea);
UINT32 src = LOAD_REG32(modrm); UINT32 src = LOAD_REG32(modrm);
WRITE32(ea, dst + src); WRITE32(cpustate,ea, dst + src);
STORE_REG32(modrm, dst); STORE_REG32(modrm, dst);
CYCLES(CYCLES_XADD_REG_MEM); CYCLES(cpustate,CYCLES_XADD_REG_MEM);
} }
} }
static void I486OP(group0F01_16)(void) // Opcode 0x0f 01 static void I486OP(group0F01_16)(i386_state *cpustate) // Opcode 0x0f 01
{ {
UINT8 modrm = FETCH(); UINT8 modrm = FETCH(cpustate);
UINT16 address; UINT16 address;
UINT32 ea; UINT32 ea;
@ -203,13 +203,13 @@ static void I486OP(group0F01_16)(void) // Opcode 0x0f 01
{ {
if( modrm >= 0xc0 ) { if( modrm >= 0xc0 ) {
address = LOAD_RM16(modrm); address = LOAD_RM16(modrm);
ea = i386_translate( CS, address ); ea = i386_translate( cpustate, CS, address );
} else { } else {
ea = GetEA(modrm); ea = GetEA(cpustate,modrm);
} }
WRITE16(ea, I.gdtr.limit); WRITE16(cpustate,ea, cpustate->gdtr.limit);
WRITE32(ea + 2, I.gdtr.base & 0xffffff); WRITE32(cpustate,ea + 2, cpustate->gdtr.base & 0xffffff);
CYCLES(CYCLES_SGDT); CYCLES(cpustate,CYCLES_SGDT);
break; break;
} }
case 1: /* SIDT */ case 1: /* SIDT */
@ -217,52 +217,52 @@ static void I486OP(group0F01_16)(void) // Opcode 0x0f 01
if (modrm >= 0xc0) if (modrm >= 0xc0)
{ {
address = LOAD_RM16(modrm); address = LOAD_RM16(modrm);
ea = i386_translate( CS, address ); ea = i386_translate( cpustate, CS, address );
} }
else else
{ {
ea = GetEA(modrm); ea = GetEA(cpustate,modrm);
} }
WRITE16(ea, I.idtr.limit); WRITE16(cpustate,ea, cpustate->idtr.limit);
WRITE32(ea + 2, I.idtr.base & 0xffffff); WRITE32(cpustate,ea + 2, cpustate->idtr.base & 0xffffff);
CYCLES(CYCLES_SIDT); CYCLES(cpustate,CYCLES_SIDT);
break; break;
} }
case 2: /* LGDT */ case 2: /* LGDT */
{ {
if( modrm >= 0xc0 ) { if( modrm >= 0xc0 ) {
address = LOAD_RM16(modrm); address = LOAD_RM16(modrm);
ea = i386_translate( CS, address ); ea = i386_translate( cpustate, CS, address );
} else { } else {
ea = GetEA(modrm); ea = GetEA(cpustate,modrm);
} }
I.gdtr.limit = READ16(ea); cpustate->gdtr.limit = READ16(cpustate,ea);
I.gdtr.base = READ32(ea + 2) & 0xffffff; cpustate->gdtr.base = READ32(cpustate,ea + 2) & 0xffffff;
CYCLES(CYCLES_LGDT); CYCLES(cpustate,CYCLES_LGDT);
break; break;
} }
case 3: /* LIDT */ case 3: /* LIDT */
{ {
if( modrm >= 0xc0 ) { if( modrm >= 0xc0 ) {
address = LOAD_RM16(modrm); address = LOAD_RM16(modrm);
ea = i386_translate( CS, address ); ea = i386_translate( cpustate, CS, address );
} else { } else {
ea = GetEA(modrm); ea = GetEA(cpustate,modrm);
} }
I.idtr.limit = READ16(ea); cpustate->idtr.limit = READ16(cpustate,ea);
I.idtr.base = READ32(ea + 2) & 0xffffff; cpustate->idtr.base = READ32(cpustate,ea + 2) & 0xffffff;
CYCLES(CYCLES_LIDT); CYCLES(cpustate,CYCLES_LIDT);
break; break;
} }
case 4: /* SMSW */ case 4: /* SMSW */
{ {
if( modrm >= 0xc0 ) { if( modrm >= 0xc0 ) {
STORE_RM16(modrm, I.cr[0]); STORE_RM16(modrm, cpustate->cr[0]);
CYCLES(CYCLES_SMSW_REG); CYCLES(cpustate,CYCLES_SMSW_REG);
} else { } else {
UINT32 ea = GetEA(modrm); UINT32 ea = GetEA(cpustate,modrm);
WRITE16(ea, I.cr[0]); WRITE16(cpustate,ea, cpustate->cr[0]);
CYCLES(CYCLES_SMSW_MEM); CYCLES(cpustate,CYCLES_SMSW_MEM);
} }
break; break;
} }
@ -272,14 +272,14 @@ static void I486OP(group0F01_16)(void) // Opcode 0x0f 01
UINT8 b; UINT8 b;
if( modrm >= 0xc0 ) { if( modrm >= 0xc0 ) {
b = LOAD_RM8(modrm); b = LOAD_RM8(modrm);
CYCLES(CYCLES_LMSW_REG); CYCLES(cpustate,CYCLES_LMSW_REG);
} else { } else {
ea = GetEA(modrm); ea = GetEA(cpustate,modrm);
CYCLES(CYCLES_LMSW_MEM); CYCLES(cpustate,CYCLES_LMSW_MEM);
b = READ8(ea); b = READ8(cpustate,ea);
} }
I.cr[0] &= ~0x03; cpustate->cr[0] &= ~0x03;
I.cr[0] |= b & 0x03; cpustate->cr[0] |= b & 0x03;
break; break;
} }
case 7: /* INVLPG */ case 7: /* INVLPG */
@ -288,14 +288,14 @@ static void I486OP(group0F01_16)(void) // Opcode 0x0f 01
break; break;
} }
default: default:
fatalerror("i486: unimplemented opcode 0x0f 01 /%d at %08X", (modrm >> 3) & 0x7, I.eip - 2); fatalerror("i486: unimplemented opcode 0x0f 01 /%d at %08X", (modrm >> 3) & 0x7, cpustate->eip - 2);
break; break;
} }
} }
static void I486OP(group0F01_32)(void) // Opcode 0x0f 01 static void I486OP(group0F01_32)(i386_state *cpustate) // Opcode 0x0f 01
{ {
UINT8 modrm = FETCH(); UINT8 modrm = FETCH(cpustate);
UINT32 address, ea; UINT32 address, ea;
switch( (modrm >> 3) & 0x7 ) switch( (modrm >> 3) & 0x7 )
@ -304,13 +304,13 @@ static void I486OP(group0F01_32)(void) // Opcode 0x0f 01
{ {
if( modrm >= 0xc0 ) { if( modrm >= 0xc0 ) {
address = LOAD_RM32(modrm); address = LOAD_RM32(modrm);
ea = i386_translate( CS, address ); ea = i386_translate( cpustate, CS, address );
} else { } else {
ea = GetEA(modrm); ea = GetEA(cpustate,modrm);
} }
WRITE16(ea, I.gdtr.limit); WRITE16(cpustate,ea, cpustate->gdtr.limit);
WRITE32(ea + 2, I.gdtr.base); WRITE32(cpustate,ea + 2, cpustate->gdtr.base);
CYCLES(CYCLES_SGDT); CYCLES(cpustate,CYCLES_SGDT);
break; break;
} }
case 1: /* SIDT */ case 1: /* SIDT */
@ -318,41 +318,41 @@ static void I486OP(group0F01_32)(void) // Opcode 0x0f 01
if (modrm >= 0xc0) if (modrm >= 0xc0)
{ {
address = LOAD_RM32(modrm); address = LOAD_RM32(modrm);
ea = i386_translate( CS, address ); ea = i386_translate( cpustate, CS, address );
} }
else else
{ {
ea = GetEA(modrm); ea = GetEA(cpustate,modrm);
} }
WRITE16(ea, I.idtr.limit); WRITE16(cpustate,ea, cpustate->idtr.limit);
WRITE32(ea + 2, I.idtr.base); WRITE32(cpustate,ea + 2, cpustate->idtr.base);
CYCLES(CYCLES_SIDT); CYCLES(cpustate,CYCLES_SIDT);
break; break;
} }
case 2: /* LGDT */ case 2: /* LGDT */
{ {
if( modrm >= 0xc0 ) { if( modrm >= 0xc0 ) {
address = LOAD_RM32(modrm); address = LOAD_RM32(modrm);
ea = i386_translate( CS, address ); ea = i386_translate( cpustate, CS, address );
} else { } else {
ea = GetEA(modrm); ea = GetEA(cpustate,modrm);
} }
I.gdtr.limit = READ16(ea); cpustate->gdtr.limit = READ16(cpustate,ea);
I.gdtr.base = READ32(ea + 2); cpustate->gdtr.base = READ32(cpustate,ea + 2);
CYCLES(CYCLES_LGDT); CYCLES(cpustate,CYCLES_LGDT);
break; break;
} }
case 3: /* LIDT */ case 3: /* LIDT */
{ {
if( modrm >= 0xc0 ) { if( modrm >= 0xc0 ) {
address = LOAD_RM32(modrm); address = LOAD_RM32(modrm);
ea = i386_translate( CS, address ); ea = i386_translate( cpustate, CS, address );
} else { } else {
ea = GetEA(modrm); ea = GetEA(cpustate,modrm);
} }
I.idtr.limit = READ16(ea); cpustate->idtr.limit = READ16(cpustate,ea);
I.idtr.base = READ32(ea + 2); cpustate->idtr.base = READ32(cpustate,ea + 2);
CYCLES(CYCLES_LIDT); CYCLES(cpustate,CYCLES_LIDT);
break; break;
} }
case 7: /* INVLPG */ case 7: /* INVLPG */
@ -361,7 +361,7 @@ static void I486OP(group0F01_32)(void) // Opcode 0x0f 01
break; break;
} }
default: default:
fatalerror("i486: unimplemented opcode 0x0f 01 /%d at %08X", (modrm >> 3) & 0x7, I.eip - 2); fatalerror("i486: unimplemented opcode 0x0f 01 /%d at %08X", (modrm >> 3) & 0x7, cpustate->eip - 2);
break; break;
} }
} }

View File

@ -1,51 +1,51 @@
// Pentium+ specific opcodes // Pentium+ specific opcodes
static void PENTIUMOP(rdmsr)(void) // Opcode 0x0f 32 static void PENTIUMOP(rdmsr)(i386_state *cpustate) // Opcode 0x0f 32
{ {
// TODO // TODO
CYCLES(CYCLES_RDMSR); CYCLES(cpustate,CYCLES_RDMSR);
} }
static void PENTIUMOP(wrmsr)(void) // Opcode 0x0f 30 static void PENTIUMOP(wrmsr)(i386_state *cpustate) // Opcode 0x0f 30
{ {
// TODO // TODO
CYCLES(1); // TODO: correct cycle count CYCLES(cpustate,1); // TODO: correct cycle count
} }
static void PENTIUMOP(rdtsc)(void) // Opcode 0x0f 31 static void PENTIUMOP(rdtsc)(i386_state *cpustate) // Opcode 0x0f 31
{ {
UINT64 ts = I.tsc + (I.base_cycles - I.cycles); UINT64 ts = cpustate->tsc + (cpustate->base_cycles - cpustate->cycles);
REG32(EAX) = (UINT32)(ts); REG32(EAX) = (UINT32)(ts);
REG32(EDX) = (UINT32)(ts >> 32); REG32(EDX) = (UINT32)(ts >> 32);
CYCLES(CYCLES_RDTSC); CYCLES(cpustate,CYCLES_RDTSC);
} }
static void I386OP(cyrix_unknown)(void) // Opcode 0x0f 74 static void I386OP(cyrix_unknown)(i386_state *cpustate) // Opcode 0x0f 74
{ {
CYCLES(1); CYCLES(cpustate,1);
} }
static void PENTIUMOP(cmpxchg8b_m64)(void) // Opcode 0x0f c7 static void PENTIUMOP(cmpxchg8b_m64)(i386_state *cpustate) // Opcode 0x0f c7
{ {
UINT8 modm = FETCH(); UINT8 modm = FETCH(cpustate);
if( modm >= 0xc0 ) { if( modm >= 0xc0 ) {
fatalerror("invalid modm"); fatalerror("invalid modm");
} else { } else {
UINT32 ea = GetEA(modm); UINT32 ea = GetEA(cpustate,modm);
UINT64 value = READ64(ea); UINT64 value = READ64(cpustate,ea);
UINT64 edx_eax = (((UINT64) REG32(EDX)) << 32) | REG32(EAX); UINT64 edx_eax = (((UINT64) REG32(EDX)) << 32) | REG32(EAX);
UINT64 ecx_ebx = (((UINT64) REG32(ECX)) << 32) | REG32(EBX); UINT64 ecx_ebx = (((UINT64) REG32(ECX)) << 32) | REG32(EBX);
if( value == edx_eax ) { if( value == edx_eax ) {
WRITE64(ea, ecx_ebx); WRITE64(cpustate,ea, ecx_ebx);
I.ZF = 1; cpustate->ZF = 1;
CYCLES(CYCLES_CMPXCHG_REG_MEM_T); CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
} else { } else {
REG32(EDX) = (UINT32) (value >> 32); REG32(EDX) = (UINT32) (value >> 32);
REG32(EAX) = (UINT32) (value >> 0); REG32(EAX) = (UINT32) (value >> 0);
I.ZF = 0; cpustate->ZF = 0;
CYCLES(CYCLES_CMPXCHG_REG_MEM_F); CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
} }
} }
} }

View File

@ -1,6 +1,6 @@
// Intel x87 FPU opcodes // Intel x87 FPU opcodes
#define ST(x) (I.fpu_reg[(I.fpu_top + (x)) & 7]) #define ST(x) (cpustate->fpu_reg[(cpustate->fpu_top + (x)) & 7])
#define FPU_INFINITY_DOUBLE U64(0x7ff0000000000000) #define FPU_INFINITY_DOUBLE U64(0x7ff0000000000000)
#define FPU_INFINITY_SINGLE (0x7f800000) #define FPU_INFINITY_SINGLE (0x7f800000)
#define FPU_SIGN_BIT_DOUBLE U64(0x8000000000000000) #define FPU_SIGN_BIT_DOUBLE U64(0x8000000000000000)
@ -30,64 +30,64 @@
#define FPU_EXCEPTION_DENORMAL_OP 0x0002 #define FPU_EXCEPTION_DENORMAL_OP 0x0002
#define FPU_EXCEPTION_INVALID_OP 0x0001 #define FPU_EXCEPTION_INVALID_OP 0x0001
INLINE void FPU_PUSH(X87_REG value) INLINE void FPU_PUSH(i386_state *cpustate, X87_REG value)
{ {
I.fpu_top--; cpustate->fpu_top--;
if (I.fpu_top < 0) if (cpustate->fpu_top < 0)
{ {
I.fpu_top = 7; cpustate->fpu_top = 7;
} }
I.fpu_reg[I.fpu_top] = value; cpustate->fpu_reg[cpustate->fpu_top] = value;
} }
INLINE X87_REG FPU_POP(void) INLINE X87_REG FPU_POP(i386_state *cpustate)
{ {
X87_REG value = I.fpu_reg[I.fpu_top]; X87_REG value = cpustate->fpu_reg[cpustate->fpu_top];
I.fpu_tag_word |= 3 << (I.fpu_top * 2); // set FPU register tag to 3 (empty) cpustate->fpu_tag_word |= 3 << (cpustate->fpu_top * 2); // set FPU register tag to 3 (empty)
I.fpu_top++; cpustate->fpu_top++;
if (I.fpu_top > 7) if (cpustate->fpu_top > 7)
{ {
I.fpu_top = 0; cpustate->fpu_top = 0;
} }
return value; return value;
} }
static void I386OP(fpu_group_d8)(void) // Opcode 0xd8 static void I386OP(fpu_group_d8)(i386_state *cpustate) // Opcode 0xd8
{ {
UINT8 modrm = FETCH(); UINT8 modrm = FETCH(cpustate);
fatalerror("I386: FPU Op D8 %02X at %08X", modrm, I.pc-2); fatalerror("I386: FPU Op D8 %02X at %08X", modrm, cpustate->pc-2);
} }
static void I386OP(fpu_group_d9)(void) // Opcode 0xd9 static void I386OP(fpu_group_d9)(i386_state *cpustate) // Opcode 0xd9
{ {
UINT8 modrm = FETCH(); UINT8 modrm = FETCH(cpustate);
if (modrm < 0xc0) if (modrm < 0xc0)
{ {
UINT32 ea = GetEA(modrm); UINT32 ea = GetEA(cpustate,modrm);
switch ((modrm >> 3) & 0x7) switch ((modrm >> 3) & 0x7)
{ {
case 5: // FLDCW case 5: // FLDCW
{ {
I.fpu_control_word = READ16(ea); cpustate->fpu_control_word = READ16(cpustate,ea);
CYCLES(1); // TODO CYCLES(cpustate,1); // TODO
break; break;
} }
case 7: // FSTCW case 7: // FSTCW
{ {
WRITE16(ea, I.fpu_control_word); WRITE16(cpustate,ea, cpustate->fpu_control_word);
CYCLES(1); // TODO CYCLES(cpustate,1); // TODO
break; break;
} }
default: default:
fatalerror("I386: FPU Op D9 %02X at %08X", modrm, I.pc-2); fatalerror("I386: FPU Op D9 %02X at %08X", modrm, cpustate->pc-2);
} }
} }
else else
@ -98,15 +98,15 @@ static void I386OP(fpu_group_d9)(void) // Opcode 0xd9
case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
{ {
X87_REG t = ST(modrm & 7); X87_REG t = ST(modrm & 7);
FPU_PUSH(t); FPU_PUSH(cpustate,t);
CYCLES(1); // TODO CYCLES(cpustate,1); // TODO
break; break;
} }
case 0x20: // FCHS case 0x20: // FCHS
{ {
ST(0).i ^= FPU_SIGN_BIT_DOUBLE; ST(0).i ^= FPU_SIGN_BIT_DOUBLE;
CYCLES(1); // TODO CYCLES(cpustate,1); // TODO
break; break;
} }
@ -114,8 +114,8 @@ static void I386OP(fpu_group_d9)(void) // Opcode 0xd9
{ {
X87_REG t; X87_REG t;
t.f = 1.0; t.f = 1.0;
FPU_PUSH(t); FPU_PUSH(cpustate,t);
CYCLES(1); // TODO CYCLES(cpustate,1); // TODO
break; break;
} }
@ -123,29 +123,29 @@ static void I386OP(fpu_group_d9)(void) // Opcode 0xd9
{ {
X87_REG t; X87_REG t;
t.f = 0.0; t.f = 0.0;
FPU_PUSH(t); FPU_PUSH(cpustate,t);
CYCLES(1); // TODO CYCLES(cpustate,1); // TODO
break; break;
} }
default: default:
fatalerror("I386: FPU Op D9 %02X at %08X", modrm, I.pc-2); fatalerror("I386: FPU Op D9 %02X at %08X", modrm, cpustate->pc-2);
} }
} }
} }
static void I386OP(fpu_group_da)(void) // Opcode 0xda static void I386OP(fpu_group_da)(i386_state *cpustate) // Opcode 0xda
{ {
UINT8 modrm = FETCH(); UINT8 modrm = FETCH(cpustate);
fatalerror("I386: FPU Op DA %02X at %08X", modrm, I.pc-2); fatalerror("I386: FPU Op DA %02X at %08X", modrm, cpustate->pc-2);
} }
static void I386OP(fpu_group_db)(void) // Opcode 0xdb static void I386OP(fpu_group_db)(i386_state *cpustate) // Opcode 0xdb
{ {
UINT8 modrm = FETCH(); UINT8 modrm = FETCH(cpustate);
if (modrm < 0xc0) if (modrm < 0xc0)
{ {
fatalerror("I386: FPU Op DB %02X at %08X", modrm, I.pc-2); fatalerror("I386: FPU Op DB %02X at %08X", modrm, cpustate->pc-2);
} }
else else
{ {
@ -153,41 +153,41 @@ static void I386OP(fpu_group_db)(void) // Opcode 0xdb
{ {
case 0x23: // FINIT case 0x23: // FINIT
{ {
I.fpu_control_word = 0x37f; cpustate->fpu_control_word = 0x37f;
I.fpu_status_word = 0; cpustate->fpu_status_word = 0;
I.fpu_tag_word = 0xffff; cpustate->fpu_tag_word = 0xffff;
I.fpu_data_ptr = 0; cpustate->fpu_data_ptr = 0;
I.fpu_inst_ptr = 0; cpustate->fpu_inst_ptr = 0;
I.fpu_opcode = 0; cpustate->fpu_opcode = 0;
CYCLES(1); // TODO CYCLES(cpustate,1); // TODO
break; break;
} }
case 0x24: // FSETPM (treated as nop on 387+) case 0x24: // FSETPM (treated as nop on 387+)
{ {
CYCLES(1); CYCLES(cpustate,1);
break; break;
} }
default: default:
fatalerror("I386: FPU Op DB %02X at %08X", modrm, I.pc-2); fatalerror("I386: FPU Op DB %02X at %08X", modrm, cpustate->pc-2);
} }
} }
} }
static void I386OP(fpu_group_dc)(void) // Opcode 0xdc static void I386OP(fpu_group_dc)(i386_state *cpustate) // Opcode 0xdc
{ {
UINT8 modrm = FETCH(); UINT8 modrm = FETCH(cpustate);
if (modrm < 0xc0) if (modrm < 0xc0)
{ {
//UINT32 ea = GetEA(modrm); //UINT32 ea = GetEA(cpustate,modrm);
switch ((modrm >> 3) & 0x7) switch ((modrm >> 3) & 0x7)
{ {
default: default:
fatalerror("I386: FPU Op DC %02X at %08X", modrm, I.pc-2); fatalerror("I386: FPU Op DC %02X at %08X", modrm, cpustate->pc-2);
} }
} }
else else
@ -200,7 +200,7 @@ static void I386OP(fpu_group_dc)(void) // Opcode 0xdc
if ((ST(modrm & 7).i & U64(0x7fffffffffffffff)) == 0) if ((ST(modrm & 7).i & U64(0x7fffffffffffffff)) == 0)
{ {
// set result as infinity if zero divide is masked // set result as infinity if zero divide is masked
if (I.fpu_control_word & FPU_MASK_ZERO_DIVIDE) if (cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
{ {
ST(modrm & 7).i |= FPU_INFINITY_DOUBLE; ST(modrm & 7).i |= FPU_INFINITY_DOUBLE;
} }
@ -209,35 +209,35 @@ static void I386OP(fpu_group_dc)(void) // Opcode 0xdc
{ {
ST(modrm & 7).f = ST(0).f / ST(modrm & 7).f; ST(modrm & 7).f = ST(0).f / ST(modrm & 7).f;
} }
CYCLES(1); // TODO CYCLES(cpustate,1); // TODO
break; break;
} }
default: default:
fatalerror("I386: FPU Op DC %02X at %08X", modrm, I.pc-2); fatalerror("I386: FPU Op DC %02X at %08X", modrm, cpustate->pc-2);
} }
} }
} }
static void I386OP(fpu_group_dd)(void) // Opcode 0xdd static void I386OP(fpu_group_dd)(i386_state *cpustate) // Opcode 0xdd
{ {
UINT8 modrm = FETCH(); UINT8 modrm = FETCH(cpustate);
if (modrm < 0xc0) if (modrm < 0xc0)
{ {
UINT32 ea = GetEA(modrm); UINT32 ea = GetEA(cpustate,modrm);
switch ((modrm >> 3) & 0x7) switch ((modrm >> 3) & 0x7)
{ {
case 7: // FSTSW case 7: // FSTSW
{ {
WRITE16(ea, (I.fpu_status_word & ~FPU_STACK_TOP_MASK) | (I.fpu_top << 10)); WRITE16(cpustate,ea, (cpustate->fpu_status_word & ~FPU_STACK_TOP_MASK) | (cpustate->fpu_top << 10));
CYCLES(1); // TODO CYCLES(cpustate,1); // TODO
break; break;
} }
default: default:
fatalerror("I386: FPU Op DD %02X at %08X", modrm, I.pc-2); fatalerror("I386: FPU Op DD %02X at %08X", modrm, cpustate->pc-2);
} }
} }
else else
@ -245,23 +245,23 @@ static void I386OP(fpu_group_dd)(void) // Opcode 0xdd
switch (modrm & 0x3f) switch (modrm & 0x3f)
{ {
default: default:
fatalerror("I386: FPU Op DD %02X at %08X", modrm, I.pc-2); fatalerror("I386: FPU Op DD %02X at %08X", modrm, cpustate->pc-2);
} }
} }
} }
static void I386OP(fpu_group_de)(void) // Opcode 0xde static void I386OP(fpu_group_de)(i386_state *cpustate) // Opcode 0xde
{ {
UINT8 modrm = FETCH(); UINT8 modrm = FETCH(cpustate);
if (modrm < 0xc0) if (modrm < 0xc0)
{ {
// UINT32 ea = GetEA(modrm); // UINT32 ea = GetEA(cpustate,modrm);
switch ((modrm >> 3) & 0x7) switch ((modrm >> 3) & 0x7)
{ {
default: default:
fatalerror("I386: FPU Op DE %02X at %08X", modrm, I.pc-2); fatalerror("I386: FPU Op DE %02X at %08X", modrm, cpustate->pc-2);
} }
} }
else else
@ -270,27 +270,27 @@ static void I386OP(fpu_group_de)(void) // Opcode 0xde
{ {
case 0x19: // FCOMPP case 0x19: // FCOMPP
{ {
I.fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0); cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
if (ST(0).f > ST(1).f) if (ST(0).f > ST(1).f)
{ {
// C3 = 0, C2 = 0, C0 = 0 // C3 = 0, C2 = 0, C0 = 0
} }
else if (ST(0).f < ST(1).f) else if (ST(0).f < ST(1).f)
{ {
I.fpu_status_word |= FPU_C0; cpustate->fpu_status_word |= FPU_C0;
} }
else if (ST(0).f == ST(1).f) else if (ST(0).f == ST(1).f)
{ {
I.fpu_status_word |= FPU_C3; cpustate->fpu_status_word |= FPU_C3;
} }
else else
{ {
// unordered // unordered
I.fpu_status_word |= (FPU_C3 | FPU_C2 | FPU_C0); cpustate->fpu_status_word |= (FPU_C3 | FPU_C2 | FPU_C0);
} }
FPU_POP(); FPU_POP(cpustate);
FPU_POP(); FPU_POP(cpustate);
CYCLES(1); // TODO CYCLES(cpustate,1); // TODO
break; break;
} }
@ -300,7 +300,7 @@ static void I386OP(fpu_group_de)(void) // Opcode 0xde
if ((ST(0).i & U64(0x7fffffffffffffff)) == 0) if ((ST(0).i & U64(0x7fffffffffffffff)) == 0)
{ {
// set result as infinity if zero divide is masked // set result as infinity if zero divide is masked
if (I.fpu_control_word & FPU_MASK_ZERO_DIVIDE) if (cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
{ {
ST(modrm & 7).i |= FPU_INFINITY_DOUBLE; ST(modrm & 7).i |= FPU_INFINITY_DOUBLE;
} }
@ -309,29 +309,29 @@ static void I386OP(fpu_group_de)(void) // Opcode 0xde
{ {
ST(modrm & 7).f = ST(modrm & 7).f / ST(0).f; ST(modrm & 7).f = ST(modrm & 7).f / ST(0).f;
} }
FPU_POP(); FPU_POP(cpustate);
CYCLES(1); // TODO CYCLES(cpustate,1); // TODO
break; break;
} }
default: default:
fatalerror("I386: FPU Op DE %02X at %08X", modrm, I.pc-2); fatalerror("I386: FPU Op DE %02X at %08X", modrm, cpustate->pc-2);
} }
} }
} }
static void I386OP(fpu_group_df)(void) // Opcode 0xdf static void I386OP(fpu_group_df)(i386_state *cpustate) // Opcode 0xdf
{ {
UINT8 modrm = FETCH(); UINT8 modrm = FETCH(cpustate);
if (modrm < 0xc0) if (modrm < 0xc0)
{ {
// UINT32 ea = GetEA(modrm); // UINT32 ea = GetEA(cpustate,modrm);
switch ((modrm >> 3) & 0x7) switch ((modrm >> 3) & 0x7)
{ {
default: default:
fatalerror("I386: FPU Op DF %02X at %08X", modrm, I.pc-2); fatalerror("I386: FPU Op DF %02X at %08X", modrm, cpustate->pc-2);
} }
} }
else else
@ -340,13 +340,13 @@ static void I386OP(fpu_group_df)(void) // Opcode 0xdf
{ {
case 0x20: // FSTSW AX case 0x20: // FSTSW AX
{ {
REG16(AX) = (I.fpu_status_word & ~FPU_STACK_TOP_MASK) | (I.fpu_top << 10); REG16(AX) = (cpustate->fpu_status_word & ~FPU_STACK_TOP_MASK) | (cpustate->fpu_top << 10);
CYCLES(1); // TODO CYCLES(cpustate,1); // TODO
break; break;
} }
default: default:
fatalerror("I386: FPU Op DF %02X at %08X", modrm, I.pc-2); fatalerror("I386: FPU Op DF %02X at %08X", modrm, cpustate->pc-2);
} }
} }
} }