Remove remaining references to 32-bit addresses in x86-64 recompiler.

This commit is contained in:
SarahW 2016-08-28 15:58:30 +01:00
commit 6aef53e854
9 changed files with 509 additions and 237 deletions

View file

@ -483,7 +483,7 @@ static uint32_t ropFSTSW_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, u
int host_reg;
FP_ENTER();
host_reg = LOAD_VAR_W(&npxs);
host_reg = LOAD_VAR_W(&cpu_state.npxs);
STORE_REG_TARGET_W_RELEASE(host_reg, REG_AX);
return op_pc;
@ -579,7 +579,7 @@ static uint32_t ropFLDCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_W(target_seg);
STORE_HOST_REG_ADDR_W((uintptr_t)&npxc, 0);
STORE_HOST_REG_ADDR_W((uintptr_t)&cpu_state.npxc, 0);
return op_pc + 1;
}
@ -594,7 +594,7 @@ static uint32_t ropFSTCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint
CHECK_SEG_WRITE(target_seg);
host_reg = LOAD_VAR_W((uintptr_t)&npxc);
host_reg = LOAD_VAR_W((uintptr_t)&cpu_state.npxc);
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
return op_pc + 1;

View file

@ -4,6 +4,9 @@
#define HOST_REG_XMM_START 0
#define HOST_REG_XMM_END 7
#define IS_32_ADDR(x) !(((uintptr_t)x) & 0xffffffff00000000)
static inline int find_host_xmm_reg()
{
int c;
@ -515,7 +518,12 @@ static void STORE_IMM_ADDR_L(uintptr_t addr, uint32_t val)
}
else
{
fatal("addr > 32-bit\n");
addbyte(0x48); /*MOV ESI, &addr*/
addbyte(0xb8 | REG_ESI);
addquad(addr);
addbyte(0xc7); /*MOVL [ESI], val*/
addbyte(0x00 | REG_ESI);
addlong(val);
}
}
@ -859,11 +867,23 @@ static void CHECK_SEG_READ(x86seg *seg)
if (seg->checked)
return;
addbyte(0x83); /*CMP seg->base, -1*/
addbyte(0x3c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
addbyte(-1);
if (IS_32_ADDR(&seg->base))
{
addbyte(0x83); /*CMP seg->base, -1*/
addbyte(0x3c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
addbyte(-1);
}
else
{
addbyte(0x48); /*MOV RSI, &addr*/
addbyte(0xb8 | REG_ESI);
addquad((uint64_t)&seg->base);
addbyte(0x83); /*CMP RSI, -1*/
addbyte(0xe8 | REG_ESI);
addbyte(0xff);
}
addbyte(0x0f); /*JE end*/
addbyte(0x84);
addlong(BLOCK_EXIT_OFFSET - (block_pos + 4));
@ -881,11 +901,23 @@ static void CHECK_SEG_WRITE(x86seg *seg)
if (seg->checked)
return;
addbyte(0x83); /*CMP seg->base, -1*/
addbyte(0x3c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
addbyte(-1);
if (IS_32_ADDR(&seg->base))
{
addbyte(0x83); /*CMP seg->base, -1*/
addbyte(0x3c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
addbyte(-1);
}
else
{
addbyte(0x48); /*MOV RSI, &addr*/
addbyte(0xb8 | REG_ESI);
addquad((uint64_t)&seg->base);
addbyte(0x83); /*CMP RSI, -1*/
addbyte(0xe8 | REG_ESI);
addbyte(0xff);
}
addbyte(0x0f); /*JE end*/
addbyte(0x84);
addlong(BLOCK_EXIT_OFFSET - (block_pos + 4));
@ -894,10 +926,20 @@ static void CHECK_SEG_WRITE(x86seg *seg)
}
static void CHECK_SEG_LIMITS(x86seg *seg, int end_offset)
{
if (IS_32_ADDR(&seg->base))
{
addbyte(0xb8 | REG_ESI); /*MOV ESI, &addr*/
addlong((uint32_t)seg);
}
else
{
addbyte(0x48); /*MOV RSI, &addr*/
addbyte(0xb8 | REG_ESI);
addquad((uint64_t)seg);
}
addbyte(0x3b); /*CMP EAX, seg->limit_low*/
addbyte(0x04);
addbyte(0x25);
addlong((uint32_t)&seg->limit_low);
addbyte(0x46);
addbyte((uintptr_t)&seg->limit_low - (uintptr_t)seg);
addbyte(0x0f); /*JB BLOCK_GPF_OFFSET*/
addbyte(0x82);
addlong(BLOCK_GPF_OFFSET - (block_pos + 4));
@ -907,9 +949,8 @@ static void CHECK_SEG_LIMITS(x86seg *seg, int end_offset)
addbyte(0xc0);
addbyte(end_offset);
addbyte(0x3b); /*CMP EAX, seg->limit_high*/
addbyte(0x04);
addbyte(0x25);
addlong((uint32_t)&seg->limit_high);
addbyte(0x46);
addbyte((uintptr_t)&seg->limit_high - (uintptr_t)seg);
addbyte(0x0f); /*JNBE BLOCK_GPF_OFFSET*/
addbyte(0x87);
addlong(BLOCK_GPF_OFFSET - (block_pos + 4));
@ -919,14 +960,23 @@ static void CHECK_SEG_LIMITS(x86seg *seg, int end_offset)
}
}
#define IS_32_ADDR(x) !(((uintptr_t)x) & 0xffffffff00000000)
static void MEM_LOAD_ADDR_EA_B(x86seg *seg)
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
}
else
{
addbyte(0x48); /*MOV RSI, &seg->base*/
addbyte(0xb8 | REG_ESI);
addquad((uint64_t)&seg->base);
addbyte(0x8b); /*MOV ECX, [RSI]*/
addbyte(0x0e);
}
addbyte(0x67); /*LEA ESI, (EAX,ECX)*/
addbyte(0x8d);
addbyte(0x34);
@ -980,10 +1030,21 @@ static void MEM_LOAD_ADDR_EA_B(x86seg *seg)
}
static void MEM_LOAD_ADDR_EA_W(x86seg *seg)
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
}
else
{
addbyte(0x48); /*MOV RSI, &seg->base*/
addbyte(0xb8 | REG_ESI);
addquad((uint64_t)&seg->base);
addbyte(0x8b); /*MOV ECX, [RSI]*/
addbyte(0x0e);
}
addbyte(0x67); /*LEA ESI, (EAX,ECX)*/
addbyte(0x8d);
addbyte(0x34);
@ -1046,10 +1107,21 @@ static void MEM_LOAD_ADDR_EA_W(x86seg *seg)
}
static void MEM_LOAD_ADDR_EA_L(x86seg *seg)
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
}
else
{
addbyte(0x48); /*MOV RSI, &seg->base*/
addbyte(0xb8 | REG_ESI);
addquad((uint64_t)&seg->base);
addbyte(0x8b); /*MOV ECX, [RSI]*/
addbyte(0x0e);
}
addbyte(0x67); /*LEA ESI, (EAX,ECX)*/
addbyte(0x8d);
addbyte(0x34);
@ -1111,10 +1183,21 @@ static void MEM_LOAD_ADDR_EA_L(x86seg *seg)
}
static void MEM_LOAD_ADDR_EA_Q(x86seg *seg)
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
}
else
{
addbyte(0x48); /*MOV RSI, &seg->base*/
addbyte(0xb8 | REG_ESI);
addquad((uint64_t)&seg->base);
addbyte(0x8b); /*MOV ECX, [RSI]*/
addbyte(0x0e);
}
addbyte(0x67); /*LEA ESI, (EAX,ECX)*/
addbyte(0x8d);
addbyte(0x34);
@ -1219,10 +1302,21 @@ static void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg)
addbyte(8);
host_reg = 8;
}
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
}
else
{
addbyte(0x48); /*MOV RSI, &seg->base*/
addbyte(0xb8 | REG_ESI);
addquad((uint64_t)&seg->base);
addbyte(0x8b); /*MOV ECX, [RSI]*/
addbyte(0x0e);
}
addbyte(0x67); /*LEA ESI, (EAX,ECX)*/
addbyte(0x8d);
addbyte(0x34);
@ -1287,10 +1381,21 @@ static void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg)
}
static void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg)
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
}
else
{
addbyte(0x48); /*MOV RSI, &seg->base*/
addbyte(0xb8 | REG_ESI);
addquad((uint64_t)&seg->base);
addbyte(0x8b); /*MOV ECX, [RSI]*/
addbyte(0x0e);
}
addbyte(0x67); /*LEA ESI, (EAX,ECX)*/
addbyte(0x8d);
addbyte(0x34);
@ -1366,10 +1471,21 @@ static void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg)
}
static void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg)
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
}
else
{
addbyte(0x48); /*MOV RSI, &seg->base*/
addbyte(0xb8 | REG_ESI);
addquad((uint64_t)&seg->base);
addbyte(0x8b); /*MOV ECX, [RSI]*/
addbyte(0x0e);
}
addbyte(0x67); /*LEA ESI, (EAX,ECX)*/
addbyte(0x8d);
addbyte(0x34);
@ -1443,10 +1559,21 @@ static void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg)
}
static void MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2)
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
if (IS_32_ADDR(&seg->base))
{
addbyte(0x8b); /*MOVL ECX, seg->base*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t)&seg->base);
}
else
{
addbyte(0x48); /*MOV RSI, &seg->base*/
addbyte(0xb8 | REG_ESI);
addquad((uint64_t)&seg->base);
addbyte(0x8b); /*MOV ECX, [RSI]*/
addbyte(0x0e);
}
addbyte(0x67); /*LEA ESI, (EAX,ECX)*/
addbyte(0x8d);
addbyte(0x34);
@ -1560,10 +1687,27 @@ static void STORE_HOST_REG_ADDR_BL(uintptr_t addr, int host_reg)
addbyte(0xb6);
addbyte(0xc0 | (REG_ECX << 3) | (host_reg & 7));
}
addbyte(0x89); /*MOV addr, EBX*/
addbyte(0x04 | (REG_ECX << 3));
addbyte(0x25);
addlong(addr);
if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100)
{
addbyte(0x89); /*MOV addr, ECX*/
addbyte(0x45 | (REG_ECX << 3));
addbyte((uint32_t)addr - (uint32_t)&cpu_state - 128);
}
else if (IS_32_ADDR(addr))
{
addbyte(0x89); /*MOV addr, ECX*/
addbyte(0x04 | (REG_ECX << 3));
addbyte(0x25);
addlong(addr);
}
else
{
addbyte(0x48); /*MOV RSI, addr*/
addbyte(0xb8 | REG_ESI);
addquad((uint64_t)addr);
addbyte(0x89); /*MOV [RSI], ECX*/
addbyte(0x0e);
}
}
static void STORE_HOST_REG_ADDR_WL(uintptr_t addr, int host_reg)
{
@ -1578,13 +1722,21 @@ static void STORE_HOST_REG_ADDR_WL(uintptr_t addr, int host_reg)
addbyte(0x45 | (REG_ECX << 3));
addbyte((uint32_t)addr - (uint32_t)&cpu_state - 128);
}
else
else if (IS_32_ADDR(addr))
{
addbyte(0x89); /*MOV addr, ECX*/
addbyte(0x04 | (REG_ECX << 3));
addbyte(0x25);
addlong(addr);
}
else
{
addbyte(0x48); /*MOV RSI, addr*/
addbyte(0xb8 | REG_ESI);
addquad((uint64_t)addr);
addbyte(0x89); /*MOV [RSI], ECX*/
addbyte(0x0e);
}
}
static void STORE_HOST_REG_ADDR_W(uintptr_t addr, int host_reg)
{
@ -1597,16 +1749,28 @@ static void STORE_HOST_REG_ADDR_W(uintptr_t addr, int host_reg)
addbyte(0x45 | ((host_reg & 7) << 3));
addbyte((uint32_t)addr - (uint32_t)&cpu_state - 128);
}
else
else if (IS_32_ADDR(addr))
{
addbyte(0x66);
if (host_reg & 8)
addbyte(0x44);
addbyte(0x89); /*MOVL addr,host_reg*/
addbyte(0x89); /*MOVW addr,host_reg*/
addbyte(0x04 | ((host_reg & 7) << 3));
addbyte(0x25);
addlong(addr);
}
else
{
addbyte(0x48); /*MOV RSI, addr*/
addbyte(0xb8 | REG_ESI);
addquad((uint64_t)addr);
addbyte(0x66);
if (host_reg & 8)
addbyte(0x44);
addbyte(0x89); /*MOVW [RSI],host_reg*/
addbyte(0x06 | ((host_reg & 7) << 3));
}
}
static void STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg)
{
@ -1618,7 +1782,7 @@ static void STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg)
addbyte(0x45 | ((host_reg & 7) << 3));
addbyte((uint32_t)addr - (uint32_t)&cpu_state - 128);
}
else
else if (IS_32_ADDR(addr))
{
if (host_reg & 8)
addbyte(0x44);
@ -1627,6 +1791,17 @@ static void STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg)
addbyte(0x25);
addlong(addr);
}
else
{
addbyte(0x48); /*MOV RSI, addr*/
addbyte(0xb8 | REG_ESI);
addquad((uint64_t)addr);
if (host_reg & 8)
addbyte(0x44);
addbyte(0x89); /*MOVL [RSI],host_reg*/
addbyte(0x06 | ((host_reg & 7) << 3));
}
}
static void AND_HOST_REG_B(int dst_reg, int src_reg)
@ -3008,11 +3183,30 @@ static int LOAD_VAR_W(uintptr_t addr)
{
int host_reg = REG_EBX;
addbyte(0x0f); /*MOVZX host_reg,[reg]*/
addbyte(0xb7);
addbyte(0x04 | (host_reg << 3));
addbyte(0x25);
addlong((uint32_t)addr);
if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100)
{
addbyte(0x0f); /*MOVZX host_reg, offset[cpu_state]*/
addbyte(0xb7);
addbyte(0x45 | (host_reg << 3));
addbyte(addr - (uintptr_t)&cpu_state - 128);
}
else if (IS_32_ADDR(addr))
{
addbyte(0x0f); /*MOVZX host_reg,[reg]*/
addbyte(0xb7);
addbyte(0x04 | (host_reg << 3));
addbyte(0x25);
addlong((uint32_t)addr);
}
else
{
addbyte(0x48); /*MOV host_reg, &addr*/
addbyte(0xb8 | host_reg);
addquad(addr);
addbyte(0x0f); /*MOVZX host_reg, [host_reg]*/
addbyte(0xb7);
addbyte(host_reg | (host_reg << 3));
}
return host_reg;
}
@ -3020,10 +3214,27 @@ static int LOAD_VAR_L(uintptr_t addr)
{
int host_reg = REG_EBX;
addbyte(0x8b); /*MOVL host_reg,[reg]*/
addbyte(0x04 | (host_reg << 3));
addbyte(0x25);
addlong((uint32_t)addr);
if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100)
{
addbyte(0x8b); /*MOVL host_reg, offset[cpu_state]*/
addbyte(0x45 | (host_reg << 3));
addbyte(addr - (uintptr_t)&cpu_state - 128);
}
else if (IS_32_ADDR(addr))
{
addbyte(0x8b); /*MOVL host_reg,[reg]*/
addbyte(0x04 | (host_reg << 3));
addbyte(0x25);
addlong((uint32_t)addr);
}
else
{
addbyte(0x48); /*MOV host_reg, &addr*/
addbyte(0xb8 | host_reg);
addquad(addr);
addbyte(0x8b); /*MOVL host_reg, [host_reg]*/
addbyte(host_reg | (host_reg << 3));
}
return host_reg;
}
@ -3323,12 +3534,23 @@ static void FP_ENTER()
{
if (codegen_fpu_entered)
return;
addbyte(0xf6); /*TEST cr0, 0xc*/
addbyte(0x04);
addbyte(0x25);
addlong((uintptr_t)&cr0);
addbyte(0xc);
if (IS_32_ADDR(&cr0))
{
addbyte(0xf6); /*TEST cr0, 0xc*/
addbyte(0x04);
addbyte(0x25);
addlong((uintptr_t)&cr0);
addbyte(0x0c);
}
else
{
addbyte(0x48); /*MOV RAX, &cr0*/
addbyte(0xb8 | REG_EAX);
addquad(&cr0);
addbyte(0xf6); /*TEST [RAX], 0xc*/
addbyte(0 | (REG_EAX << 3));
addbyte(0x0c);
}
addbyte(0x74); /*JZ +*/
addbyte(7+5+12+5);
addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/
@ -3773,7 +3995,7 @@ static int64_t x87_fround(double b)
{
int64_t a, c;
switch ((npxc>>10)&3)
switch ((cpu_state.npxc >> 10) & 3)
{
case 0: /*Nearest*/
a = (int64_t)floor(b);
@ -4131,7 +4353,7 @@ static void FP_OP_D(int op)
addbyte(0x0f);
addbyte(0x6e);
addbyte(0xc8);
if (((npxc >> 10) & 3) && op == FPU_ADD)
if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD)
{
addbyte(0x0f); /*STMXCSR [ESP+8]*/
addbyte(0xae);
@ -4145,7 +4367,7 @@ static void FP_OP_D(int op)
addbyte(0x25); /*AND EAX, ~(3 << 13)*/
addlong(~(3 << 10));
addbyte(0x0d); /*OR EAX, (npxc & (3 << 10)) << 3*/
addlong((npxc & (3 << 10)) << 3);
addlong((cpu_state.npxc & (3 << 10)) << 3);
addbyte(0x89); /*MOV [RSP+12], EAX*/
addbyte(0x44);
addbyte(0x24);
@ -4157,7 +4379,7 @@ static void FP_OP_D(int op)
addbyte(0x0c);
}
FP_OP_MEM(op);
if (((npxc >> 10) & 3) && op == FPU_ADD)
if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD)
{
addbyte(0x0f); /*LDMXCSR [RSP+8]*/
addbyte(0xae);
@ -4209,9 +4431,8 @@ static void FP_COMPARE_REG(int dst, int src)
}
addbyte(0x8a); /*MOV CL, [npxs+1]*/
addbyte(0x0c);
addbyte(0x25);
addlong(((uintptr_t)&npxs) + 1);
addbyte(0x4d);
addbyte(cpu_state_offset(npxs) + 1);
// addbyte(0xdb); /*FCLEX*/
// addbyte(0xe2);
addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/
@ -4256,9 +4477,8 @@ static void FP_COMPARE_REG(int dst, int src)
addbyte(0x08); /*OR CL, AH*/
addbyte(0xe1);
addbyte(0x88); /*MOV [npxs+1], CL*/
addbyte(0x0c);
addbyte(0x25);
addlong(((uintptr_t)&npxs) + 1);
addbyte(0x4d);
addbyte(cpu_state_offset(npxs) + 1);
}
static void FP_COMPARE_MEM()
@ -4268,9 +4488,8 @@ static void FP_COMPARE_MEM()
addbyte(cpu_state_offset(TOP));
addbyte(0x8a); /*MOV CL, [npxs+1]*/
addbyte(0x0c);
addbyte(0x25);
addlong(((uintptr_t)&npxs) + 1);
addbyte(0x4d);
addbyte(cpu_state_offset(npxs) + 1);
// addbyte(0xdb); /*FCLEX*/
// addbyte(0xe2);
addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/
@ -4293,9 +4512,8 @@ static void FP_COMPARE_MEM()
addbyte(0x08); /*OR CL, AH*/
addbyte(0xe1);
addbyte(0x88); /*MOV [npxs+1], CL*/
addbyte(0x0c);
addbyte(0x25);
addlong(((uintptr_t)&npxs) + 1);
addbyte(0x4d);
addbyte(cpu_state_offset(npxs) + 1);
}
static void FP_COMPARE_S()
{
@ -4340,40 +4558,83 @@ static void FP_COMPARE_IL()
static void SET_BITS(uintptr_t addr, uint32_t val)
{
if (val & ~0xff)
if (IS_32_ADDR(addr))
{
addbyte(0x81);
addbyte(0x0c);
addbyte(0x25);
addlong(addr);
addlong(val);
if (val & ~0xff)
{
addbyte(0x81); /*OR [addr], val*/
addbyte(0x0c);
addbyte(0x25);
addlong(addr);
addlong(val);
}
else
{
addbyte(0x80); /*OR [addr], val*/
addbyte(0x0c);
addbyte(0x25);
addlong(addr);
addbyte(val);
}
}
else
{
addbyte(0x80);
addbyte(0x0c);
addbyte(0x25);
addlong(addr);
addbyte(val);
{
addbyte(0x48); /*MOV RAX, &addr*/
addbyte(0xb8 | REG_EAX);
addquad(addr);
if (val & ~0xff)
{
addbyte(0x81); /*OR [RAX], val*/
addbyte(0x08);
addlong(val);
}
else
{
addbyte(0x80); /*OR [RAX], val*/
addbyte(0x08);
addbyte(val);
}
}
}
static void CLEAR_BITS(uintptr_t addr, uint32_t val)
{
if (val & ~0xff)
if (IS_32_ADDR(addr))
{
addbyte(0x81);
addbyte(0x24);
addbyte(0x25);
addlong(addr);
addlong(~val);
if (val & ~0xff)
{
addbyte(0x81); /*AND [addr], val*/
addbyte(0x24);
addbyte(0x25);
addlong(addr);
addlong(~val);
}
else
{
addbyte(0x80); /*AND [addr], val*/
addbyte(0x24);
addbyte(0x25);
addlong(addr);
addbyte(~val);
}
}
else
{
addbyte(0x80);
addbyte(0x24);
addbyte(0x25);
addlong(addr);
addbyte(~val);
{
addbyte(0x48); /*MOV RAX, &addr*/
addbyte(0xb8 | REG_EAX);
addquad(addr);
if (val & ~0xff)
{
addbyte(0x81); /*AND [RAX], val*/
addbyte(0x20);
addlong(~val);
}
else
{
addbyte(0x80); /*AND [RAX], val*/
addbyte(0x20);
addbyte(~val);
}
}
}
@ -4385,11 +4646,23 @@ static void MMX_ENTER()
if (codegen_mmx_entered)
return;
addbyte(0xf6); /*TEST cr0, 0xc*/
addbyte(0x04);
addbyte(0x25);
addlong((uintptr_t)&cr0);
addbyte(0xc);
if (IS_32_ADDR(&cr0))
{
addbyte(0xf6); /*TEST cr0, 0xc*/
addbyte(0x04);
addbyte(0x25);
addlong((uintptr_t)&cr0);
addbyte(0x0c);
}
else
{
addbyte(0x48); /*MOV RAX, &cr0*/
addbyte(0xb8 | REG_EAX);
addquad(&cr0);
addbyte(0xf6); /*TEST [RAX], 0xc*/
addbyte(0 | (REG_EAX << 3));
addbyte(0x0c);
}
addbyte(0x74); /*JZ +*/
addbyte(7+5+12+5);
addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/

View file

@ -2307,10 +2307,10 @@ static double _fp_half = 0.5;
static void FP_LOAD_ROUNDING()
{
pclog("npxc %04x\n", npxc);
pclog("cpu_state.npxc %04x\n", cpu_state.npxc);
addbyte(0x8b); /*MOV EDX, npxc*/
addbyte(0x15);
addlong((uintptr_t)&npxc);
addlong((uintptr_t)&cpu_state.npxc);
addbyte(0xd9); /*FSTCW [ESP+8]*/
addbyte(0x7c);
addbyte(0x24);
@ -2336,7 +2336,7 @@ static int32_t x87_fround32(double b)
{
int64_t a, c;
switch ((npxc>>10)&3)
switch ((cpu_state.npxc >> 10) & 3)
{
case 0: /*Nearest*/
a = (int64_t)floor(b);
@ -2359,7 +2359,7 @@ static int64_t x87_fround64(double b)
{
int64_t a, c;
switch ((npxc>>10)&3)
switch ((cpu_state.npxc >> 10) & 3)
{
case 0: /*Nearest*/
a = (int64_t)floor(b);
@ -2599,7 +2599,7 @@ static void FP_OP_D(int op)
addbyte(0x89); /*MOV [ESP], EAX*/
addbyte(0x04);
addbyte(0x24);
if (((npxc >> 10) & 3) && op == FPU_ADD)
if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD)
{
addbyte(0x9b); /*FSTCW [ESP+8]*/
addbyte(0xd9);
@ -2616,7 +2616,7 @@ static void FP_OP_D(int op)
addword(~(3 << 10));
addbyte(0x66); /*OR AX, npxc & (3 << 10)*/
addbyte(0x0d);
addword(npxc & (3 << 10));
addword(cpu_state.npxc & (3 << 10));
addbyte(0x66); /*MOV [ESP+12], AX*/
addbyte(0x89);
addbyte(0x44);
@ -2647,7 +2647,7 @@ static void FP_OP_D(int op)
addbyte(0x5c);
addbyte(0xdd);
addbyte(cpu_state_offset(ST));
if (((npxc >> 10) & 3) && op == FPU_ADD)
if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD)
{
addbyte(0xd9); /*FLDCW [ESP+8]*/
addbyte(0x6c);
@ -2753,8 +2753,8 @@ static void FP_COMPARE_S()
addbyte(0xdd);
addbyte(cpu_state_offset(ST));
addbyte(0x8a); /*MOV BL, [npxs+1]*/
addbyte(0x1d);
addlong(((uintptr_t)&npxs) + 1);
addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1);
addbyte(0xdb); /*FCLEX*/
addbyte(0xe2);
addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/
@ -2771,8 +2771,8 @@ static void FP_COMPARE_S()
addbyte(0x08); /*OR BL, AH*/
addbyte(0xe3);
addbyte(0x88); /*MOV [npxs+1], BL*/
addbyte(0x1d);
addlong(((uintptr_t)&npxs) + 1);
addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1);
}
static void FP_COMPARE_D()
{
@ -2791,8 +2791,8 @@ static void FP_COMPARE_D()
addbyte(0xdd);
addbyte(cpu_state_offset(ST));
addbyte(0x8a); /*MOV BL, [npxs+1]*/
addbyte(0x1d);
addlong(((uintptr_t)&npxs) + 1);
addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1);
addbyte(0xdb); /*FCLEX*/
addbyte(0xe2);
addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/
@ -2809,8 +2809,8 @@ static void FP_COMPARE_D()
addbyte(0x08); /*OR BL, AH*/
addbyte(0xe3);
addbyte(0x88); /*MOV [npxs+1], BL*/
addbyte(0x1d);
addlong(((uintptr_t)&npxs) + 1);
addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1);
}
static void FP_COMPARE_IW()
{
@ -2825,8 +2825,8 @@ static void FP_COMPARE_IW()
addbyte(0xdd);
addbyte(cpu_state_offset(ST));
addbyte(0x8a); /*MOV BL, [npxs+1]*/
addbyte(0x1d);
addlong(((uintptr_t)&npxs) + 1);
addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1);
addbyte(0xdb); /*FCLEX*/
addbyte(0xe2);
addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/
@ -2843,8 +2843,8 @@ static void FP_COMPARE_IW()
addbyte(0x08); /*OR BL, AH*/
addbyte(0xe3);
addbyte(0x88); /*MOV [npxs+1], BL*/
addbyte(0x1d);
addlong(((uintptr_t)&npxs) + 1);
addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1);
}
static void FP_COMPARE_IL()
{
@ -2859,8 +2859,8 @@ static void FP_COMPARE_IL()
addbyte(0xdd);
addbyte(cpu_state_offset(ST));
addbyte(0x8a); /*MOV BL, [npxs+1]*/
addbyte(0x1d);
addlong(((uintptr_t)&npxs) + 1);
addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1);
addbyte(0xdb); /*FCLEX*/
addbyte(0xe2);
addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/
@ -2877,8 +2877,8 @@ static void FP_COMPARE_IL()
addbyte(0x08); /*OR BL, AH*/
addbyte(0xe3);
addbyte(0x88); /*MOV [npxs+1], BL*/
addbyte(0x1d);
addlong(((uintptr_t)&npxs) + 1);
addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1);
}
static void FP_OP_REG(int op, int dst, int src)
@ -2962,8 +2962,8 @@ static void FP_COMPARE_REG(int dst, int src)
}
addbyte(0x8a); /*MOV CL, [npxs+1]*/
addbyte(0x0d);
addlong(((uintptr_t)&npxs) + 1);
addbyte(0x4d);
addbyte(cpu_state_offset(npxs) + 1);
addbyte(0xdb); /*FCLEX*/
addbyte(0xe2);
addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/
@ -3001,8 +3001,8 @@ static void FP_COMPARE_REG(int dst, int src)
addbyte(0x08); /*OR CL, AH*/
addbyte(0xe1);
addbyte(0x88); /*MOV [npxs+1], CL*/
addbyte(0x0d);
addlong(((uintptr_t)&npxs) + 1);
addbyte(0x4d);
addbyte(cpu_state_offset(npxs) + 1);
}
static int ZERO_EXTEND_W_B(int reg)

View file

@ -155,6 +155,8 @@ struct
int _cycles;
int cpu_recomp_ins;
uint16_t npxs, npxc;
double ST[8];

View file

@ -19,8 +19,6 @@
#include "x87.h"
#include "386_common.h"
uint16_t npxs,npxc;
uint16_t x87_gettag()
{
uint16_t ret = 0;
@ -61,7 +59,7 @@ void x87_dumpregs()
pclog("ST(0)=%f\tST(1)=%f\tST(2)=%f\tST(3)=%f\t\n",cpu_state.ST[cpu_state.TOP],cpu_state.ST[(cpu_state.TOP+1)&7],cpu_state.ST[(cpu_state.TOP+2)&7],cpu_state.ST[(cpu_state.TOP+3)&7]);
pclog("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t\n",cpu_state.ST[(cpu_state.TOP+4)&7],cpu_state.ST[(cpu_state.TOP+5)&7],cpu_state.ST[(cpu_state.TOP+6)&7],cpu_state.ST[(cpu_state.TOP+7)&7]);
}
pclog("Status = %04X Control = %04X Tag = %04X\n",npxs,npxc,x87_gettag());
pclog("Status = %04X Control = %04X Tag = %04X\n", cpu_state.npxs, cpu_state.npxc, x87_gettag());
}
void x87_print()
@ -74,7 +72,7 @@ void x87_print()
else
{
pclog("\tST(0)=%.20f\tST(1)=%.20f\tST(2)=%f\tST(3)=%f\t",cpu_state.ST[cpu_state.TOP&7],cpu_state.ST[(cpu_state.TOP+1)&7],cpu_state.ST[(cpu_state.TOP+2)&7],cpu_state.ST[(cpu_state.TOP+3)&7]);
pclog("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\tTOP=%i CR=%04X SR=%04X TAG=%04X\n",cpu_state.ST[(cpu_state.TOP+4)&7],cpu_state.ST[(cpu_state.TOP+5)&7],cpu_state.ST[(cpu_state.TOP+6)&7],cpu_state.ST[(cpu_state.TOP+7)&7], cpu_state.TOP, npxc, npxs, x87_gettag());
pclog("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\tTOP=%i CR=%04X SR=%04X TAG=%04X\n",cpu_state.ST[(cpu_state.TOP+4)&7],cpu_state.ST[(cpu_state.TOP+5)&7],cpu_state.ST[(cpu_state.TOP+6)&7],cpu_state.ST[(cpu_state.TOP+7)&7], cpu_state.TOP, cpu_state.npxc, cpu_state.npxs, x87_gettag());
}
}

View file

@ -1,6 +1,5 @@
uint32_t x87_pc_off,x87_op_off;
uint16_t x87_pc_seg,x87_op_seg;
extern uint16_t npxs, npxc;
static inline void x87_set_mmx();
static inline void x87_emms();

View file

@ -18,8 +18,8 @@ static int rounding_modes[4] = {FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZ
{ \
if (((double)src2) == 0.0) \
{ \
npxs |= STATUS_ZERODIVIDE; \
if (npxc & STATUS_ZERODIVIDE) \
cpu_state.npxs |= STATUS_ZERODIVIDE; \
if (cpu_state.npxc & STATUS_ZERODIVIDE) \
dst = src1 / (double)src2; \
else \
{ \
@ -68,7 +68,7 @@ static inline int64_t x87_fround(double b)
{
int64_t a, c;
switch ((npxc>>10)&3)
switch ((cpu_state.npxc >> 10) & 3)
{
case 0: /*Nearest*/
a = (int64_t)floor(b);

View file

@ -5,10 +5,10 @@ static int opFADD ## name ## _a ## a_size(uint32_t fetchdat) \
FP_ENTER(); \
fetch_ea_ ## a_size(fetchdat); \
load_var = get(); if (cpu_state.abrt) return 1; \
if ((npxc >> 10) & 3) \
fesetround(rounding_modes[(npxc >> 10) & 3]); \
if ((cpu_state.npxc >> 10) & 3) \
fesetround(rounding_modes[(cpu_state.npxc >> 10) & 3]); \
ST(0) += use_var; \
if ((npxc >> 10) & 3) \
if ((cpu_state.npxc >> 10) & 3) \
fesetround(FE_TONEAREST); \
cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \
CLOCK_CYCLES(8); \
@ -20,8 +20,8 @@ static int opFCOM ## name ## _a ## a_size(uint32_t fetchdat) \
FP_ENTER(); \
fetch_ea_ ## a_size(fetchdat); \
load_var = get(); if (cpu_state.abrt) return 1; \
npxs &= ~(C0|C2|C3); \
npxs |= x87_compare(ST(0), (double)use_var); \
cpu_state.npxs &= ~(C0|C2|C3); \
cpu_state.npxs |= x87_compare(ST(0), (double)use_var); \
CLOCK_CYCLES(4); \
return 0; \
} \
@ -31,8 +31,8 @@ static int opFCOMP ## name ## _a ## a_size(uint32_t fetchdat) \
FP_ENTER(); \
fetch_ea_ ## a_size(fetchdat); \
load_var = get(); if (cpu_state.abrt) return 1; \
npxs &= ~(C0|C2|C3); \
npxs |= x87_compare(ST(0), (double)use_var); \
cpu_state.npxs &= ~(C0|C2|C3); \
cpu_state.npxs |= x87_compare(ST(0), (double)use_var); \
x87_pop(); \
CLOCK_CYCLES(4); \
return 0; \
@ -144,9 +144,9 @@ static int opFCOM(uint32_t fetchdat)
FP_ENTER();
cpu_state.pc++;
if (fplog) pclog("FCOM\n");
npxs &= ~(C0|C2|C3);
if (ST(0) == ST(fetchdat & 7)) npxs |= C3;
else if (ST(0) < ST(fetchdat & 7)) npxs |= C0;
cpu_state.npxs &= ~(C0|C2|C3);
if (ST(0) == ST(fetchdat & 7)) cpu_state.npxs |= C3;
else if (ST(0) < ST(fetchdat & 7)) cpu_state.npxs |= C0;
CLOCK_CYCLES(4);
return 0;
}
@ -156,8 +156,8 @@ static int opFCOMP(uint32_t fetchdat)
FP_ENTER();
cpu_state.pc++;
if (fplog) pclog("FCOMP\n");
npxs &= ~(C0|C2|C3);
npxs |= x87_compare(ST(0), ST(fetchdat & 7));
cpu_state.npxs &= ~(C0|C2|C3);
cpu_state.npxs |= x87_compare(ST(0), ST(fetchdat & 7));
x87_pop();
CLOCK_CYCLES(4);
return 0;
@ -168,11 +168,11 @@ static int opFCOMPP(uint32_t fetchdat)
FP_ENTER();
cpu_state.pc++;
if (fplog) pclog("FCOMPP\n");
npxs &= ~(C0|C2|C3);
cpu_state.npxs &= ~(C0|C2|C3);
if (*(uint64_t *)&ST(0) == ((uint64_t)1 << 63) && *(uint64_t *)&ST(1) == 0)
npxs |= C0; /*Nasty hack to fix 80387 detection*/
cpu_state.npxs |= C0; /*Nasty hack to fix 80387 detection*/
else
npxs |= x87_compare(ST(0), ST(1));
cpu_state.npxs |= x87_compare(ST(0), ST(1));
x87_pop();
x87_pop();
@ -184,8 +184,8 @@ static int opFUCOMPP(uint32_t fetchdat)
FP_ENTER();
cpu_state.pc++;
if (fplog) pclog("FUCOMPP\n", easeg, cpu_state.eaaddr);
npxs &= ~(C0|C2|C3);
npxs |= x87_ucompare(ST(0), ST(1));
cpu_state.npxs &= ~(C0|C2|C3);
cpu_state.npxs |= x87_ucompare(ST(0), ST(1));
x87_pop();
x87_pop();
CLOCK_CYCLES(5);
@ -383,8 +383,8 @@ static int opFUCOM(uint32_t fetchdat)
FP_ENTER();
cpu_state.pc++;
if (fplog) pclog("FUCOM\n");
npxs &= ~(C0|C2|C3);
npxs |= x87_ucompare(ST(0), ST(fetchdat & 7));
cpu_state.npxs &= ~(C0|C2|C3);
cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7));
CLOCK_CYCLES(4);
return 0;
}
@ -394,8 +394,8 @@ static int opFUCOMP(uint32_t fetchdat)
FP_ENTER();
cpu_state.pc++;
if (fplog) pclog("FUCOMP\n");
npxs &= ~(C0|C2|C3);
npxs |= x87_ucompare(ST(0), ST(fetchdat & 7));
cpu_state.npxs &= ~(C0|C2|C3);
cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7));
x87_pop();
CLOCK_CYCLES(4);
return 0;

View file

@ -3,7 +3,7 @@ static int opFSTSW_AX(uint32_t fetchdat)
FP_ENTER();
cpu_state.pc++;
if (fplog) pclog("FSTSW\n");
AX = npxs;
AX = cpu_state.npxs;
CLOCK_CYCLES(3);
return 0;
}
@ -22,7 +22,7 @@ static int opFCLEX(uint32_t fetchdat)
{
FP_ENTER();
cpu_state.pc++;
npxs &= 0xff00;
cpu_state.npxs &= 0xff00;
CLOCK_CYCLES(4);
return 0;
}
@ -31,8 +31,8 @@ static int opFINIT(uint32_t fetchdat)
{
FP_ENTER();
cpu_state.pc++;
npxc = 0x37F;
npxs = 0;
cpu_state.npxc = 0x37F;
cpu_state.npxs = 0;
*(uint64_t *)cpu_state.tag = 0x0303030303030303ll;
cpu_state.TOP = 0;
CLOCK_CYCLES(17);
@ -84,18 +84,18 @@ static int FSTOR()
{
case 0x000: /*16-bit real mode*/
case 0x001: /*16-bit protected mode*/
npxc = readmemw(easeg, cpu_state.eaaddr);
npxs = readmemw(easeg, cpu_state.eaaddr+2);
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2);
x87_settag(readmemw(easeg, cpu_state.eaaddr+4));
cpu_state.TOP = (npxs >> 11) & 7;
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
cpu_state.eaaddr += 14;
break;
case 0x100: /*32-bit real mode*/
case 0x101: /*32-bit protected mode*/
npxc = readmemw(easeg, cpu_state.eaaddr);
npxs = readmemw(easeg, cpu_state.eaaddr+4);
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4);
x87_settag(readmemw(easeg, cpu_state.eaaddr+8));
cpu_state.TOP = (npxs >> 11) & 7;
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
cpu_state.eaaddr += 28;
break;
}
@ -139,13 +139,13 @@ static int FSAVE()
{
FP_ENTER();
if (fplog) pclog("FSAVE %08X:%08X %i\n", easeg, cpu_state.eaaddr, cpu_state.ismmx);
npxs = (npxs & ~(7 << 11)) | (cpu_state.TOP << 11);
cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | (cpu_state.TOP << 11);
switch ((cr0 & 1) | (cpu_state.op32 & 0x100))
{
case 0x000: /*16-bit real mode*/
writememw(easeg,cpu_state.eaaddr,npxc);
writememw(easeg,cpu_state.eaaddr+2,npxs);
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs);
writememw(easeg,cpu_state.eaaddr+4,x87_gettag());
writememw(easeg,cpu_state.eaaddr+6,x87_pc_off);
writememw(easeg,cpu_state.eaaddr+10,x87_op_off);
@ -174,8 +174,8 @@ static int FSAVE()
}
break;
case 0x001: /*16-bit protected mode*/
writememw(easeg,cpu_state.eaaddr,npxc);
writememw(easeg,cpu_state.eaaddr+2,npxs);
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs);
writememw(easeg,cpu_state.eaaddr+4,x87_gettag());
writememw(easeg,cpu_state.eaaddr+6,x87_pc_off);
writememw(easeg,cpu_state.eaaddr+8,x87_pc_seg);
@ -206,8 +206,8 @@ static int FSAVE()
}
break;
case 0x100: /*32-bit real mode*/
writememw(easeg,cpu_state.eaaddr,npxc);
writememw(easeg,cpu_state.eaaddr+4,npxs);
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
writememw(easeg,cpu_state.eaaddr+4,cpu_state.npxs);
writememw(easeg,cpu_state.eaaddr+8,x87_gettag());
writememw(easeg,cpu_state.eaaddr+12,x87_pc_off);
writememw(easeg,cpu_state.eaaddr+20,x87_op_off);
@ -237,8 +237,8 @@ static int FSAVE()
}
break;
case 0x101: /*32-bit protected mode*/
writememw(easeg,cpu_state.eaaddr,npxc);
writememw(easeg,cpu_state.eaaddr+4,npxs);
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
writememw(easeg,cpu_state.eaaddr+4,cpu_state.npxs);
writememw(easeg,cpu_state.eaaddr+8,x87_gettag());
writememl(easeg,cpu_state.eaaddr+12,x87_pc_off);
writememl(easeg,cpu_state.eaaddr+16,x87_pc_seg);
@ -292,7 +292,7 @@ static int opFSTSW_a16(uint32_t fetchdat)
FP_ENTER();
fetch_ea_16(fetchdat);
if (fplog) pclog("FSTSW %08X:%08X\n", easeg, cpu_state.eaaddr);
seteaw((npxs & 0xC7FF) | (cpu_state.TOP << 11));
seteaw((cpu_state.npxs & 0xC7FF) | (cpu_state.TOP << 11));
CLOCK_CYCLES(3);
return cpu_state.abrt;
}
@ -301,7 +301,7 @@ static int opFSTSW_a32(uint32_t fetchdat)
FP_ENTER();
fetch_ea_32(fetchdat);
if (fplog) pclog("FSTSW %08X:%08X\n", easeg, cpu_state.eaaddr);
seteaw((npxs & 0xC7FF) | (cpu_state.TOP << 11));
seteaw((cpu_state.npxs & 0xC7FF) | (cpu_state.TOP << 11));
CLOCK_CYCLES(3);
return cpu_state.abrt;
}
@ -373,9 +373,9 @@ static int opFTST(uint32_t fetchdat)
FP_ENTER();
cpu_state.pc++;
if (fplog) pclog("FTST\n");
npxs &= ~(C0|C2|C3);
if (ST(0) == 0.0) npxs |= C3;
else if (ST(0) < 0.0) npxs |= C0;
cpu_state.npxs &= ~(C0|C2|C3);
if (ST(0) == 0.0) cpu_state.npxs |= C3;
else if (ST(0) < 0.0) cpu_state.npxs |= C0;
CLOCK_CYCLES(4);
return 0;
}
@ -385,11 +385,11 @@ static int opFXAM(uint32_t fetchdat)
FP_ENTER();
cpu_state.pc++;
if (fplog) pclog("FXAM %i %f\n", cpu_state.tag[cpu_state.TOP&7], ST(0));
npxs &= ~(C0|C1|C2|C3);
if (cpu_state.tag[cpu_state.TOP&7] == 3) npxs |= (C0|C3);
else if (ST(0) == 0.0) npxs |= C3;
else npxs |= C2;
if (ST(0) < 0.0) npxs |= C1;
cpu_state.npxs &= ~(C0|C1|C2|C3);
if (cpu_state.tag[cpu_state.TOP&7] == 3) cpu_state.npxs |= (C0|C3);
else if (ST(0) == 0.0) cpu_state.npxs |= C3;
else cpu_state.npxs |= C2;
if (ST(0) < 0.0) cpu_state.npxs |= C1;
CLOCK_CYCLES(8);
return 0;
}
@ -508,7 +508,7 @@ static int opFPTAN(uint32_t fetchdat)
ST(0) = tan(ST(0));
cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
x87_push(1.0);
npxs &= ~C2;
cpu_state.npxs &= ~C2;
CLOCK_CYCLES(235);
return 0;
}
@ -555,10 +555,10 @@ static int opFPREM(uint32_t fetchdat)
ST(0) = ST(0) - (ST(1) * (double)temp64);
cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
if (fplog) pclog("%f\n", ST(0));
npxs &= ~(C0|C1|C2|C3);
if (temp64 & 4) npxs|=C0;
if (temp64 & 2) npxs|=C3;
if (temp64 & 1) npxs|=C1;
cpu_state.npxs &= ~(C0|C1|C2|C3);
if (temp64 & 4) cpu_state.npxs|=C0;
if (temp64 & 2) cpu_state.npxs|=C3;
if (temp64 & 1) cpu_state.npxs|=C1;
CLOCK_CYCLES(100);
return 0;
}
@ -572,10 +572,10 @@ static int opFPREM1(uint32_t fetchdat)
ST(0) = ST(0) - (ST(1) * (double)temp64);
cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
if (fplog) pclog("%f\n", ST(0));
npxs &= ~(C0|C1|C2|C3);
if (temp64 & 4) npxs|=C0;
if (temp64 & 2) npxs|=C3;
if (temp64 & 1) npxs|=C1;
cpu_state.npxs &= ~(C0|C1|C2|C3);
if (temp64 & 4) cpu_state.npxs|=C0;
if (temp64 & 2) cpu_state.npxs|=C3;
if (temp64 & 1) cpu_state.npxs|=C1;
CLOCK_CYCLES(100);
return 0;
}
@ -601,7 +601,7 @@ static int opFSINCOS(uint32_t fetchdat)
ST(0) = sin(td);
cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
x87_push(cos(td));
npxs &= ~C2;
cpu_state.npxs &= ~C2;
CLOCK_CYCLES(330);
return 0;
}
@ -638,7 +638,7 @@ static int opFSIN(uint32_t fetchdat)
if (fplog) pclog("FSIN\n");
ST(0) = sin(ST(0));
cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
npxs &= ~C2;
cpu_state.npxs &= ~C2;
CLOCK_CYCLES(300);
return 0;
}
@ -650,7 +650,7 @@ static int opFCOS(uint32_t fetchdat)
if (fplog) pclog("FCOS\n");
ST(0) = cos(ST(0));
cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
npxs &= ~C2;
cpu_state.npxs &= ~C2;
CLOCK_CYCLES(300);
return 0;
}
@ -664,17 +664,17 @@ static int FLDENV()
{
case 0x000: /*16-bit real mode*/
case 0x001: /*16-bit protected mode*/
npxc = readmemw(easeg, cpu_state.eaaddr);
npxs = readmemw(easeg, cpu_state.eaaddr+2);
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2);
x87_settag(readmemw(easeg, cpu_state.eaaddr+4));
cpu_state.TOP = (npxs >> 11) & 7;
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
break;
case 0x100: /*32-bit real mode*/
case 0x101: /*32-bit protected mode*/
npxc = readmemw(easeg, cpu_state.eaaddr);
npxs = readmemw(easeg, cpu_state.eaaddr+4);
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4);
x87_settag(readmemw(easeg, cpu_state.eaaddr+8));
cpu_state.TOP = (npxs >> 11) & 7;
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
break;
}
CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
@ -704,7 +704,7 @@ static int opFLDCW_a16(uint32_t fetchdat)
if (fplog) pclog("FLDCW %08X:%08X\n", easeg, cpu_state.eaaddr);
tempw = geteaw();
if (cpu_state.abrt) return 1;
npxc = tempw;
cpu_state.npxc = tempw;
CLOCK_CYCLES(4);
return 0;
}
@ -716,7 +716,7 @@ static int opFLDCW_a32(uint32_t fetchdat)
if (fplog) pclog("FLDCW %08X:%08X\n", easeg, cpu_state.eaaddr);
tempw = geteaw();
if (cpu_state.abrt) return 1;
npxc = tempw;
cpu_state.npxc = tempw;
CLOCK_CYCLES(4);
return 0;
}
@ -728,15 +728,15 @@ static int FSTENV()
switch ((cr0 & 1) | (cpu_state.op32 & 0x100))
{
case 0x000: /*16-bit real mode*/
writememw(easeg,cpu_state.eaaddr,npxc);
writememw(easeg,cpu_state.eaaddr+2,npxs);
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs);
writememw(easeg,cpu_state.eaaddr+4,x87_gettag());
writememw(easeg,cpu_state.eaaddr+6,x87_pc_off);
writememw(easeg,cpu_state.eaaddr+10,x87_op_off);
break;
case 0x001: /*16-bit protected mode*/
writememw(easeg,cpu_state.eaaddr,npxc);
writememw(easeg,cpu_state.eaaddr+2,npxs);
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs);
writememw(easeg,cpu_state.eaaddr+4,x87_gettag());
writememw(easeg,cpu_state.eaaddr+6,x87_pc_off);
writememw(easeg,cpu_state.eaaddr+8,x87_pc_seg);
@ -744,16 +744,16 @@ static int FSTENV()
writememw(easeg,cpu_state.eaaddr+12,x87_op_seg);
break;
case 0x100: /*32-bit real mode*/
writememw(easeg,cpu_state.eaaddr,npxc);
writememw(easeg,cpu_state.eaaddr+4,npxs);
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
writememw(easeg,cpu_state.eaaddr+4,cpu_state.npxs);
writememw(easeg,cpu_state.eaaddr+8,x87_gettag());
writememw(easeg,cpu_state.eaaddr+12,x87_pc_off);
writememw(easeg,cpu_state.eaaddr+20,x87_op_off);
writememl(easeg,cpu_state.eaaddr+24,(x87_op_off>>16)<<12);
break;
case 0x101: /*32-bit protected mode*/
writememw(easeg,cpu_state.eaaddr,npxc);
writememw(easeg,cpu_state.eaaddr+4,npxs);
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
writememw(easeg,cpu_state.eaaddr+4,cpu_state.npxs);
writememw(easeg,cpu_state.eaaddr+8,x87_gettag());
writememl(easeg,cpu_state.eaaddr+12,x87_pc_off);
writememl(easeg,cpu_state.eaaddr+16,x87_pc_seg);
@ -785,7 +785,7 @@ static int opFSTCW_a16(uint32_t fetchdat)
FP_ENTER();
fetch_ea_16(fetchdat);
if (fplog) pclog("FSTCW %08X:%08X\n", easeg, cpu_state.eaaddr);
seteaw(npxc);
seteaw(cpu_state.npxc);
CLOCK_CYCLES(3);
return cpu_state.abrt;
}
@ -794,7 +794,7 @@ static int opFSTCW_a32(uint32_t fetchdat)
FP_ENTER();
fetch_ea_32(fetchdat);
if (fplog) pclog("FSTCW %08X:%08X\n", easeg, cpu_state.eaaddr);
seteaw(npxc);
seteaw(cpu_state.npxc);
CLOCK_CYCLES(3);
return cpu_state.abrt;
}