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

View File

@ -1,199 +1,199 @@
// 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))
{
case 0:
{
REG32(EAX) = I.cpuid_max_input_value_eax;
REG32(EBX) = I.cpuid_id0;
REG32(ECX) = I.cpuid_id2;
REG32(EDX) = I.cpuid_id1;
CYCLES(CYCLES_CPUID);
REG32(EAX) = cpustate->cpuid_max_input_value_eax;
REG32(EBX) = cpustate->cpuid_id0;
REG32(ECX) = cpustate->cpuid_id2;
REG32(EDX) = cpustate->cpuid_id1;
CYCLES(cpustate,CYCLES_CPUID);
break;
}
case 1:
{
REG32(EAX) = I.cpu_version;
REG32(EDX) = I.feature_flags;
CYCLES(CYCLES_CPUID_EAX1);
REG32(EAX) = cpustate->cpu_version;
REG32(EDX) = cpustate->feature_flags;
CYCLES(cpustate,CYCLES_CPUID_EAX1);
break;
}
}
}
static void I486OP(invd)(void) // Opcode 0x0f 08
static void I486OP(invd)(i386_state *cpustate) // Opcode 0x0f 08
{
// 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 ?
}
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 ) {
UINT8 dst = LOAD_RM8(modrm);
UINT8 src = LOAD_REG8(modrm);
if( REG8(AL) == dst ) {
STORE_RM8(modrm, src);
I.ZF = 1;
CYCLES(CYCLES_CMPXCHG_REG_REG_T);
cpustate->ZF = 1;
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T);
} else {
REG8(AL) = dst;
I.ZF = 0;
CYCLES(CYCLES_CMPXCHG_REG_REG_F);
cpustate->ZF = 0;
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F);
}
} else {
UINT32 ea = GetEA(modrm);
UINT8 dst = READ8(ea);
UINT32 ea = GetEA(cpustate,modrm);
UINT8 dst = READ8(cpustate,ea);
UINT8 src = LOAD_REG8(modrm);
if( REG8(AL) == dst ) {
WRITE8(modrm, src);
I.ZF = 1;
CYCLES(CYCLES_CMPXCHG_REG_MEM_T);
WRITE8(cpustate,modrm, src);
cpustate->ZF = 1;
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
} else {
REG8(AL) = dst;
I.ZF = 0;
CYCLES(CYCLES_CMPXCHG_REG_MEM_F);
cpustate->ZF = 0;
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 ) {
UINT16 dst = LOAD_RM16(modrm);
UINT16 src = LOAD_REG16(modrm);
if( REG16(AX) == dst ) {
STORE_RM16(modrm, src);
I.ZF = 1;
CYCLES(CYCLES_CMPXCHG_REG_REG_T);
cpustate->ZF = 1;
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T);
} else {
REG16(AX) = dst;
I.ZF = 0;
CYCLES(CYCLES_CMPXCHG_REG_REG_F);
cpustate->ZF = 0;
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F);
}
} else {
UINT32 ea = GetEA(modrm);
UINT16 dst = READ16(ea);
UINT32 ea = GetEA(cpustate,modrm);
UINT16 dst = READ16(cpustate,ea);
UINT16 src = LOAD_REG16(modrm);
if( REG16(AX) == dst ) {
WRITE16(modrm, src);
I.ZF = 1;
CYCLES(CYCLES_CMPXCHG_REG_MEM_T);
WRITE16(cpustate,modrm, src);
cpustate->ZF = 1;
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
} else {
REG16(AX) = dst;
I.ZF = 0;
CYCLES(CYCLES_CMPXCHG_REG_MEM_F);
cpustate->ZF = 0;
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 ) {
UINT32 dst = LOAD_RM32(modrm);
UINT32 src = LOAD_REG32(modrm);
if( REG32(EAX) == dst ) {
STORE_RM32(modrm, src);
I.ZF = 1;
CYCLES(CYCLES_CMPXCHG_REG_REG_T);
cpustate->ZF = 1;
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T);
} else {
REG32(EAX) = dst;
I.ZF = 0;
CYCLES(CYCLES_CMPXCHG_REG_REG_F);
cpustate->ZF = 0;
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F);
}
} else {
UINT32 ea = GetEA(modrm);
UINT32 dst = READ32(ea);
UINT32 ea = GetEA(cpustate,modrm);
UINT32 dst = READ32(cpustate,ea);
UINT32 src = LOAD_REG32(modrm);
if( REG32(EAX) == dst ) {
WRITE32(ea, src);
I.ZF = 1;
CYCLES(CYCLES_CMPXCHG_REG_MEM_T);
WRITE32(cpustate,ea, src);
cpustate->ZF = 1;
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
} else {
REG32(EAX) = dst;
I.ZF = 0;
CYCLES(CYCLES_CMPXCHG_REG_MEM_F);
cpustate->ZF = 0;
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 ) {
UINT8 dst = LOAD_RM8(modrm);
UINT8 src = LOAD_REG8(modrm);
STORE_RM16(modrm, dst + src);
STORE_REG16(modrm, dst);
CYCLES(CYCLES_XADD_REG_REG);
CYCLES(cpustate,CYCLES_XADD_REG_REG);
} else {
UINT32 ea = GetEA(modrm);
UINT8 dst = READ8(ea);
UINT32 ea = GetEA(cpustate,modrm);
UINT8 dst = READ8(cpustate,ea);
UINT8 src = LOAD_REG8(modrm);
WRITE8(ea, dst + src);
WRITE8(cpustate,ea, dst + src);
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 ) {
UINT16 dst = LOAD_RM16(modrm);
UINT16 src = LOAD_REG16(modrm);
STORE_RM16(modrm, dst + src);
STORE_REG16(modrm, dst);
CYCLES(CYCLES_XADD_REG_REG);
CYCLES(cpustate,CYCLES_XADD_REG_REG);
} else {
UINT32 ea = GetEA(modrm);
UINT16 dst = READ16(ea);
UINT32 ea = GetEA(cpustate,modrm);
UINT16 dst = READ16(cpustate,ea);
UINT16 src = LOAD_REG16(modrm);
WRITE16(ea, dst + src);
WRITE16(cpustate,ea, dst + src);
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 ) {
UINT32 dst = LOAD_RM32(modrm);
UINT32 src = LOAD_REG32(modrm);
STORE_RM32(modrm, dst + src);
STORE_REG32(modrm, dst);
CYCLES(CYCLES_XADD_REG_REG);
CYCLES(cpustate,CYCLES_XADD_REG_REG);
} else {
UINT32 ea = GetEA(modrm);
UINT32 dst = READ32(ea);
UINT32 ea = GetEA(cpustate,modrm);
UINT32 dst = READ32(cpustate,ea);
UINT32 src = LOAD_REG32(modrm);
WRITE32(ea, dst + src);
WRITE32(cpustate,ea, dst + src);
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;
UINT32 ea;
@ -203,13 +203,13 @@ static void I486OP(group0F01_16)(void) // Opcode 0x0f 01
{
if( modrm >= 0xc0 ) {
address = LOAD_RM16(modrm);
ea = i386_translate( CS, address );
ea = i386_translate( cpustate, CS, address );
} else {
ea = GetEA(modrm);
ea = GetEA(cpustate,modrm);
}
WRITE16(ea, I.gdtr.limit);
WRITE32(ea + 2, I.gdtr.base & 0xffffff);
CYCLES(CYCLES_SGDT);
WRITE16(cpustate,ea, cpustate->gdtr.limit);
WRITE32(cpustate,ea + 2, cpustate->gdtr.base & 0xffffff);
CYCLES(cpustate,CYCLES_SGDT);
break;
}
case 1: /* SIDT */
@ -217,52 +217,52 @@ static void I486OP(group0F01_16)(void) // Opcode 0x0f 01
if (modrm >= 0xc0)
{
address = LOAD_RM16(modrm);
ea = i386_translate( CS, address );
ea = i386_translate( cpustate, CS, address );
}
else
{
ea = GetEA(modrm);
ea = GetEA(cpustate,modrm);
}
WRITE16(ea, I.idtr.limit);
WRITE32(ea + 2, I.idtr.base & 0xffffff);
CYCLES(CYCLES_SIDT);
WRITE16(cpustate,ea, cpustate->idtr.limit);
WRITE32(cpustate,ea + 2, cpustate->idtr.base & 0xffffff);
CYCLES(cpustate,CYCLES_SIDT);
break;
}
case 2: /* LGDT */
{
if( modrm >= 0xc0 ) {
address = LOAD_RM16(modrm);
ea = i386_translate( CS, address );
ea = i386_translate( cpustate, CS, address );
} else {
ea = GetEA(modrm);
ea = GetEA(cpustate,modrm);
}
I.gdtr.limit = READ16(ea);
I.gdtr.base = READ32(ea + 2) & 0xffffff;
CYCLES(CYCLES_LGDT);
cpustate->gdtr.limit = READ16(cpustate,ea);
cpustate->gdtr.base = READ32(cpustate,ea + 2) & 0xffffff;
CYCLES(cpustate,CYCLES_LGDT);
break;
}
case 3: /* LIDT */
{
if( modrm >= 0xc0 ) {
address = LOAD_RM16(modrm);
ea = i386_translate( CS, address );
ea = i386_translate( cpustate, CS, address );
} else {
ea = GetEA(modrm);
ea = GetEA(cpustate,modrm);
}
I.idtr.limit = READ16(ea);
I.idtr.base = READ32(ea + 2) & 0xffffff;
CYCLES(CYCLES_LIDT);
cpustate->idtr.limit = READ16(cpustate,ea);
cpustate->idtr.base = READ32(cpustate,ea + 2) & 0xffffff;
CYCLES(cpustate,CYCLES_LIDT);
break;
}
case 4: /* SMSW */
{
if( modrm >= 0xc0 ) {
STORE_RM16(modrm, I.cr[0]);
CYCLES(CYCLES_SMSW_REG);
STORE_RM16(modrm, cpustate->cr[0]);
CYCLES(cpustate,CYCLES_SMSW_REG);
} else {
UINT32 ea = GetEA(modrm);
WRITE16(ea, I.cr[0]);
CYCLES(CYCLES_SMSW_MEM);
UINT32 ea = GetEA(cpustate,modrm);
WRITE16(cpustate,ea, cpustate->cr[0]);
CYCLES(cpustate,CYCLES_SMSW_MEM);
}
break;
}
@ -272,14 +272,14 @@ static void I486OP(group0F01_16)(void) // Opcode 0x0f 01
UINT8 b;
if( modrm >= 0xc0 ) {
b = LOAD_RM8(modrm);
CYCLES(CYCLES_LMSW_REG);
CYCLES(cpustate,CYCLES_LMSW_REG);
} else {
ea = GetEA(modrm);
CYCLES(CYCLES_LMSW_MEM);
b = READ8(ea);
ea = GetEA(cpustate,modrm);
CYCLES(cpustate,CYCLES_LMSW_MEM);
b = READ8(cpustate,ea);
}
I.cr[0] &= ~0x03;
I.cr[0] |= b & 0x03;
cpustate->cr[0] &= ~0x03;
cpustate->cr[0] |= b & 0x03;
break;
}
case 7: /* INVLPG */
@ -288,14 +288,14 @@ static void I486OP(group0F01_16)(void) // Opcode 0x0f 01
break;
}
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;
}
}
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;
switch( (modrm >> 3) & 0x7 )
@ -304,13 +304,13 @@ static void I486OP(group0F01_32)(void) // Opcode 0x0f 01
{
if( modrm >= 0xc0 ) {
address = LOAD_RM32(modrm);
ea = i386_translate( CS, address );
ea = i386_translate( cpustate, CS, address );
} else {
ea = GetEA(modrm);
ea = GetEA(cpustate,modrm);
}
WRITE16(ea, I.gdtr.limit);
WRITE32(ea + 2, I.gdtr.base);
CYCLES(CYCLES_SGDT);
WRITE16(cpustate,ea, cpustate->gdtr.limit);
WRITE32(cpustate,ea + 2, cpustate->gdtr.base);
CYCLES(cpustate,CYCLES_SGDT);
break;
}
case 1: /* SIDT */
@ -318,41 +318,41 @@ static void I486OP(group0F01_32)(void) // Opcode 0x0f 01
if (modrm >= 0xc0)
{
address = LOAD_RM32(modrm);
ea = i386_translate( CS, address );
ea = i386_translate( cpustate, CS, address );
}
else
{
ea = GetEA(modrm);
ea = GetEA(cpustate,modrm);
}
WRITE16(ea, I.idtr.limit);
WRITE32(ea + 2, I.idtr.base);
CYCLES(CYCLES_SIDT);
WRITE16(cpustate,ea, cpustate->idtr.limit);
WRITE32(cpustate,ea + 2, cpustate->idtr.base);
CYCLES(cpustate,CYCLES_SIDT);
break;
}
case 2: /* LGDT */
{
if( modrm >= 0xc0 ) {
address = LOAD_RM32(modrm);
ea = i386_translate( CS, address );
ea = i386_translate( cpustate, CS, address );
} else {
ea = GetEA(modrm);
ea = GetEA(cpustate,modrm);
}
I.gdtr.limit = READ16(ea);
I.gdtr.base = READ32(ea + 2);
CYCLES(CYCLES_LGDT);
cpustate->gdtr.limit = READ16(cpustate,ea);
cpustate->gdtr.base = READ32(cpustate,ea + 2);
CYCLES(cpustate,CYCLES_LGDT);
break;
}
case 3: /* LIDT */
{
if( modrm >= 0xc0 ) {
address = LOAD_RM32(modrm);
ea = i386_translate( CS, address );
ea = i386_translate( cpustate, CS, address );
} else {
ea = GetEA(modrm);
ea = GetEA(cpustate,modrm);
}
I.idtr.limit = READ16(ea);
I.idtr.base = READ32(ea + 2);
CYCLES(CYCLES_LIDT);
cpustate->idtr.limit = READ16(cpustate,ea);
cpustate->idtr.base = READ32(cpustate,ea + 2);
CYCLES(cpustate,CYCLES_LIDT);
break;
}
case 7: /* INVLPG */
@ -361,7 +361,7 @@ static void I486OP(group0F01_32)(void) // Opcode 0x0f 01
break;
}
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;
}
}

View File

@ -1,51 +1,51 @@
// Pentium+ specific opcodes
static void PENTIUMOP(rdmsr)(void) // Opcode 0x0f 32
static void PENTIUMOP(rdmsr)(i386_state *cpustate) // Opcode 0x0f 32
{
// 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
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(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 ) {
fatalerror("invalid modm");
} else {
UINT32 ea = GetEA(modm);
UINT64 value = READ64(ea);
UINT32 ea = GetEA(cpustate,modm);
UINT64 value = READ64(cpustate,ea);
UINT64 edx_eax = (((UINT64) REG32(EDX)) << 32) | REG32(EAX);
UINT64 ecx_ebx = (((UINT64) REG32(ECX)) << 32) | REG32(EBX);
if( value == edx_eax ) {
WRITE64(ea, ecx_ebx);
I.ZF = 1;
CYCLES(CYCLES_CMPXCHG_REG_MEM_T);
WRITE64(cpustate,ea, ecx_ebx);
cpustate->ZF = 1;
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
} else {
REG32(EDX) = (UINT32) (value >> 32);
REG32(EAX) = (UINT32) (value >> 0);
I.ZF = 0;
CYCLES(CYCLES_CMPXCHG_REG_MEM_F);
cpustate->ZF = 0;
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
}
}
}

View File

@ -1,6 +1,6 @@
// 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_SINGLE (0x7f800000)
#define FPU_SIGN_BIT_DOUBLE U64(0x8000000000000000)
@ -30,64 +30,64 @@
#define FPU_EXCEPTION_DENORMAL_OP 0x0002
#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--;
if (I.fpu_top < 0)
cpustate->fpu_top--;
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++;
if (I.fpu_top > 7)
cpustate->fpu_top++;
if (cpustate->fpu_top > 7)
{
I.fpu_top = 0;
cpustate->fpu_top = 0;
}
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();
fatalerror("I386: FPU Op D8 %02X at %08X", modrm, I.pc-2);
UINT8 modrm = FETCH(cpustate);
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)
{
UINT32 ea = GetEA(modrm);
UINT32 ea = GetEA(cpustate,modrm);
switch ((modrm >> 3) & 0x7)
{
case 5: // FLDCW
{
I.fpu_control_word = READ16(ea);
CYCLES(1); // TODO
cpustate->fpu_control_word = READ16(cpustate,ea);
CYCLES(cpustate,1); // TODO
break;
}
case 7: // FSTCW
{
WRITE16(ea, I.fpu_control_word);
CYCLES(1); // TODO
WRITE16(cpustate,ea, cpustate->fpu_control_word);
CYCLES(cpustate,1); // TODO
break;
}
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
@ -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:
{
X87_REG t = ST(modrm & 7);
FPU_PUSH(t);
CYCLES(1); // TODO
FPU_PUSH(cpustate,t);
CYCLES(cpustate,1); // TODO
break;
}
case 0x20: // FCHS
{
ST(0).i ^= FPU_SIGN_BIT_DOUBLE;
CYCLES(1); // TODO
CYCLES(cpustate,1); // TODO
break;
}
@ -114,8 +114,8 @@ static void I386OP(fpu_group_d9)(void) // Opcode 0xd9
{
X87_REG t;
t.f = 1.0;
FPU_PUSH(t);
CYCLES(1); // TODO
FPU_PUSH(cpustate,t);
CYCLES(cpustate,1); // TODO
break;
}
@ -123,29 +123,29 @@ static void I386OP(fpu_group_d9)(void) // Opcode 0xd9
{
X87_REG t;
t.f = 0.0;
FPU_PUSH(t);
CYCLES(1); // TODO
FPU_PUSH(cpustate,t);
CYCLES(cpustate,1); // TODO
break;
}
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();
fatalerror("I386: FPU Op DA %02X at %08X", modrm, I.pc-2);
UINT8 modrm = FETCH(cpustate);
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)
{
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
{
@ -153,41 +153,41 @@ static void I386OP(fpu_group_db)(void) // Opcode 0xdb
{
case 0x23: // FINIT
{
I.fpu_control_word = 0x37f;
I.fpu_status_word = 0;
I.fpu_tag_word = 0xffff;
I.fpu_data_ptr = 0;
I.fpu_inst_ptr = 0;
I.fpu_opcode = 0;
cpustate->fpu_control_word = 0x37f;
cpustate->fpu_status_word = 0;
cpustate->fpu_tag_word = 0xffff;
cpustate->fpu_data_ptr = 0;
cpustate->fpu_inst_ptr = 0;
cpustate->fpu_opcode = 0;
CYCLES(1); // TODO
CYCLES(cpustate,1); // TODO
break;
}
case 0x24: // FSETPM (treated as nop on 387+)
{
CYCLES(1);
CYCLES(cpustate,1);
break;
}
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)
{
//UINT32 ea = GetEA(modrm);
//UINT32 ea = GetEA(cpustate,modrm);
switch ((modrm >> 3) & 0x7)
{
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
@ -200,7 +200,7 @@ static void I386OP(fpu_group_dc)(void) // Opcode 0xdc
if ((ST(modrm & 7).i & U64(0x7fffffffffffffff)) == 0)
{
// 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;
}
@ -209,35 +209,35 @@ static void I386OP(fpu_group_dc)(void) // Opcode 0xdc
{
ST(modrm & 7).f = ST(0).f / ST(modrm & 7).f;
}
CYCLES(1); // TODO
CYCLES(cpustate,1); // TODO
break;
}
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)
{
UINT32 ea = GetEA(modrm);
UINT32 ea = GetEA(cpustate,modrm);
switch ((modrm >> 3) & 0x7)
{
case 7: // FSTSW
{
WRITE16(ea, (I.fpu_status_word & ~FPU_STACK_TOP_MASK) | (I.fpu_top << 10));
CYCLES(1); // TODO
WRITE16(cpustate,ea, (cpustate->fpu_status_word & ~FPU_STACK_TOP_MASK) | (cpustate->fpu_top << 10));
CYCLES(cpustate,1); // TODO
break;
}
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
@ -245,23 +245,23 @@ static void I386OP(fpu_group_dd)(void) // Opcode 0xdd
switch (modrm & 0x3f)
{
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)
{
// UINT32 ea = GetEA(modrm);
// UINT32 ea = GetEA(cpustate,modrm);
switch ((modrm >> 3) & 0x7)
{
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
@ -270,27 +270,27 @@ static void I386OP(fpu_group_de)(void) // Opcode 0xde
{
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)
{
// C3 = 0, C2 = 0, C0 = 0
}
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)
{
I.fpu_status_word |= FPU_C3;
cpustate->fpu_status_word |= FPU_C3;
}
else
{
// 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();
CYCLES(1); // TODO
FPU_POP(cpustate);
FPU_POP(cpustate);
CYCLES(cpustate,1); // TODO
break;
}
@ -300,7 +300,7 @@ static void I386OP(fpu_group_de)(void) // Opcode 0xde
if ((ST(0).i & U64(0x7fffffffffffffff)) == 0)
{
// 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;
}
@ -309,29 +309,29 @@ static void I386OP(fpu_group_de)(void) // Opcode 0xde
{
ST(modrm & 7).f = ST(modrm & 7).f / ST(0).f;
}
FPU_POP();
CYCLES(1); // TODO
FPU_POP(cpustate);
CYCLES(cpustate,1); // TODO
break;
}
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)
{
// UINT32 ea = GetEA(modrm);
// UINT32 ea = GetEA(cpustate,modrm);
switch ((modrm >> 3) & 0x7)
{
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
@ -340,13 +340,13 @@ static void I386OP(fpu_group_df)(void) // Opcode 0xdf
{
case 0x20: // FSTSW AX
{
REG16(AX) = (I.fpu_status_word & ~FPU_STACK_TOP_MASK) | (I.fpu_top << 10);
CYCLES(1); // TODO
REG16(AX) = (cpustate->fpu_status_word & ~FPU_STACK_TOP_MASK) | (cpustate->fpu_top << 10);
CYCLES(cpustate,1); // TODO
break;
}
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);
}
}
}