mirror of
https://github.com/holub/mame
synced 2025-05-23 22:20:01 +03:00
Pointer-ified the i386.
This commit is contained in:
parent
129c08982e
commit
36d63663d3
File diff suppressed because it is too large
Load Diff
@ -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
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user