x86-32 recompiler compiles FPU instructions using direct access to register stack when top-of-stack is static. Minor speedup.

This commit is contained in:
SarahW 2016-09-11 15:38:05 +01:00
commit 75f9316c11
5 changed files with 1395 additions and 785 deletions

View file

@ -1348,6 +1348,13 @@ void exec386_dynarec(int cycs)
valid_block = 0; valid_block = 0;
} }
} }
if (valid_block && block->was_recompiled && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != cpu_state.TOP)
{
/*FPU top-of-stack does not match the value this block was compiled
with, re-compile using dynamic top-of-stack*/
block->flags &= ~CODEBLOCK_STATIC_TOP;
block->was_recompiled = 0;
}
} }
if (valid_block && block->was_recompiled) if (valid_block && block->was_recompiled)

View file

@ -56,10 +56,17 @@ typedef struct codeblock_t
uint64_t page_mask, page_mask2; uint64_t page_mask, page_mask2;
int was_recompiled; int was_recompiled;
uint32_t flags;
int TOP;
uint8_t data[2048]; uint8_t data[2048];
} codeblock_t; } codeblock_t;
/*Code block uses FPU*/
#define CODEBLOCK_HAS_FPU 1
/*Code block is always entered with the same FPU top-of-stack*/
#define CODEBLOCK_STATIC_TOP 2
static inline codeblock_t *codeblock_tree_find(uint32_t phys) static inline codeblock_t *codeblock_tree_find(uint32_t phys)
{ {
codeblock_t *block = pages[phys >> 12].head; codeblock_t *block = pages[phys >> 12].head;

View file

@ -1838,6 +1838,41 @@ static void FP_ENTER()
static void FP_FLD(int reg) static void FP_FLD(int reg)
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0xf3); /*MOVQ XMM0, ST[reg][EBP]*/
addbyte(0x0f);
addbyte(0x7e);
addbyte(0x45);
addbyte(cpu_state_offset(ST[(cpu_state.TOP + reg) & 7]));
addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/
addbyte(0x45);
addbyte(cpu_state_offset(TOP));
addbyte((cpu_state.TOP - 1) & 7);
addbyte(0xf3); /*MOVQ XMM1, MM[reg][EBP]*/
addbyte(0x0f);
addbyte(0x7e);
addbyte(0x4d);
addbyte(cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q));
addbyte(0x66); /*MOVQ ST[-1][EBP], XMM0*/
addbyte(0x0f);
addbyte(0xd6);
addbyte(0x45);
addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]));
addbyte(0x8a); /*MOV AL, tag[reg][EBP]*/
addbyte(0x45);
addbyte(cpu_state_offset(tag[(cpu_state.TOP + reg) & 7]));
addbyte(0x66); /*MOVQ MM[-1][EBP], XMM1*/
addbyte(0x0f);
addbyte(0xd6);
addbyte(0x4d);
addbyte(cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q));
addbyte(0x88); /*MOV tag[-1][EBP], AL*/
addbyte(0x45);
addbyte(cpu_state_offset(tag[(cpu_state.TOP - 1) & 7]));
}
else
{
addbyte(0x8b); /*MOV EAX, [TOP]*/ addbyte(0x8b); /*MOV EAX, [TOP]*/
addbyte(0x45); addbyte(0x45);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -1901,10 +1936,32 @@ static void FP_FLD(int reg)
addbyte(0x89); /*MOV [TOP], EBX*/ addbyte(0x89); /*MOV [TOP], EBX*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
}
} }
static void FP_FST(int reg) static void FP_FST(int reg)
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0xf3); /*MOVQ XMM0, ST[0][EBP]*/
addbyte(0x0f);
addbyte(0x7e);
addbyte(0x45);
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
addbyte(0x8a); /*MOV AL, tag[0][EBP]*/
addbyte(0x45);
addbyte(cpu_state_offset(tag[cpu_state.TOP]));
addbyte(0x66); /*MOVQ ST[reg][EBP], XMM0*/
addbyte(0x0f);
addbyte(0xd6);
addbyte(0x45);
addbyte(cpu_state_offset(ST[(cpu_state.TOP + reg) & 7]));
addbyte(0x88); /*MOV tag[reg][EBP], AL*/
addbyte(0x45);
addbyte(cpu_state_offset(tag[(cpu_state.TOP + reg) & 7]));
}
else
{
addbyte(0x8b); /*MOV EAX, [TOP]*/ addbyte(0x8b); /*MOV EAX, [TOP]*/
addbyte(0x45); addbyte(0x45);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -1935,10 +1992,68 @@ static void FP_FST(int reg)
addbyte(0x5c); addbyte(0x5c);
addbyte(0x05); addbyte(0x05);
addbyte(cpu_state_offset(tag[0])); addbyte(cpu_state_offset(tag[0]));
}
} }
static void FP_FXCH(int reg) static void FP_FXCH(int reg)
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0xf3); /*MOVQ XMM0, ST[0][EBP]*/
addbyte(0x0f);
addbyte(0x7e);
addbyte(0x45);
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
addbyte(0xf3); /*MOVQ XMM1, ST[reg][EBP]*/
addbyte(0x0f);
addbyte(0x7e);
addbyte(0x4d);
addbyte(cpu_state_offset(ST[(cpu_state.TOP + reg) & 7]));
addbyte(0x66); /*MOVQ ST[reg][EBP], XMM0*/
addbyte(0x0f);
addbyte(0xd6);
addbyte(0x45);
addbyte(cpu_state_offset(ST[(cpu_state.TOP + reg) & 7]));
addbyte(0xf3); /*MOVQ XMM2, MM[0][EBP]*/
addbyte(0x0f);
addbyte(0x7e);
addbyte(0x55);
addbyte(cpu_state_offset(MM[cpu_state.TOP].q));
addbyte(0x66); /*MOVQ ST[0][EBP], XMM1*/
addbyte(0x0f);
addbyte(0xd6);
addbyte(0x4d);
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
addbyte(0xf3); /*MOVQ XMM3, MM[reg][EBP]*/
addbyte(0x0f);
addbyte(0x7e);
addbyte(0x5d);
addbyte(cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q));
addbyte(0x66); /*MOVQ MM[reg][EBP], XMM2*/
addbyte(0x0f);
addbyte(0xd6);
addbyte(0x55);
addbyte(cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q));
addbyte(0x8a); /*MOV AL, tag[0][EBP]*/
addbyte(0x45);
addbyte(cpu_state_offset(tag[cpu_state.TOP]));
addbyte(0x66); /*MOVQ MM[0][EBP], XMM3*/
addbyte(0x0f);
addbyte(0xd6);
addbyte(0x5d);
addbyte(cpu_state_offset(MM[cpu_state.TOP].q));
addbyte(0x8a); /*MOV AH, tag[reg][EBP]*/
addbyte(0x65);
addbyte(cpu_state_offset(tag[(cpu_state.TOP + reg) & 7]));
addbyte(0x88); /*MOV tag[reg][EBP], AL*/
addbyte(0x45);
addbyte(cpu_state_offset(tag[(cpu_state.TOP + reg) & 7]));
addbyte(0x88); /*MOV tag[0][EBP], AH*/
addbyte(0x65);
addbyte(cpu_state_offset(tag[cpu_state.TOP]));
}
else
{
addbyte(0x8b); /*MOV EAX, [TOP]*/ addbyte(0x8b); /*MOV EAX, [TOP]*/
addbyte(0x45); addbyte(0x45);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -1947,7 +2062,7 @@ static void FP_FXCH(int reg)
addbyte(0x83); /*ADD EAX, reg*/ addbyte(0x83); /*ADD EAX, reg*/
addbyte(0xc0); addbyte(0xc0);
addbyte(reg); addbyte(reg);
//#if 0
addbyte(0xdd); /*FLD [ST+EBX*8]*/ addbyte(0xdd); /*FLD [ST+EBX*8]*/
addbyte(0x44); addbyte(0x44);
addbyte(0xdd); addbyte(0xdd);
@ -1967,8 +2082,6 @@ static void FP_FXCH(int reg)
addbyte(0x5c); addbyte(0x5c);
addbyte(0xc5); addbyte(0xc5);
addbyte(cpu_state_offset(ST)); addbyte(cpu_state_offset(ST));
// addbyte(0xbe); /*MOVL ESI, tag*/
// addlong((uintptr_t)cpu_state.tag);
addbyte(0x8a); /*MOV CL, tag[EAX]*/ addbyte(0x8a); /*MOV CL, tag[EAX]*/
addbyte(0x4c); addbyte(0x4c);
addbyte(0x05); addbyte(0x05);
@ -2015,50 +2128,37 @@ static void FP_FXCH(int reg)
addbyte(0x54); addbyte(0x54);
addbyte(0xc6); addbyte(0xc6);
addbyte(0x04); addbyte(0x04);
reg = reg; }
//#endif
#if 0
addbyte(0xbe); /*MOVL ESI, ST*/
addlong((uintptr_t)cpu_state.ST);
addbyte(0x8b); /*MOVL EDX, [ESI+EBX*8]*/
addbyte(0x14);
addbyte(0xde);
addbyte(0x83); /*AND EAX, 7*/
addbyte(0xe0);
addbyte(0x07);
addbyte(0x8b); /*MOVL ECX, [ESI+EAX*8]*/
addbyte(0x0c);
addbyte(0xc6);
addbyte(0x89); /*MOVL [ESI+EBX*8], ECX*/
addbyte(0x0c);
addbyte(0xde);
addbyte(0x89); /*MOVL [ESI+EAX*8], EDX*/
addbyte(0x14);
addbyte(0xc6);
addbyte(0x8b); /*MOVL ECX, [4+ESI+EAX*8]*/
addbyte(0x4c);
addbyte(0xc6);
addbyte(0x04);
addbyte(0x8b); /*MOVL EDX, [4+ESI+EBX*8]*/
addbyte(0x54);
addbyte(0xde);
addbyte(0x04);
addbyte(0x89); /*MOVL [4+ESI+EBX*8], ECX*/
addbyte(0x4c);
addbyte(0xde);
addbyte(0x04);
addbyte(0x89); /*MOVL [4+ESI+EAX*8], EDX*/
addbyte(0x54);
addbyte(0xc6);
addbyte(0x04);
#endif
} }
static void FP_LOAD_S() static void FP_LOAD_S()
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0x89); /*MOV [ESP], EAX*/
addbyte(0x04);
addbyte(0x24);
addbyte(0x85); /*TEST EAX, EAX*/
addbyte(0xc0);
addbyte(0xd9); /*FLD [ESP]*/
addbyte(0x04);
addbyte(0x24);
addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/
addbyte(0x45);
addbyte(cpu_state_offset(TOP));
addbyte((cpu_state.TOP - 1) & 7);
addbyte(0x0f); /*SETE tag[reg][EBP]*/
addbyte(0x94);
addbyte(0x45);
addbyte(cpu_state_offset(tag[(cpu_state.TOP - 1) & 7]));
addbyte(0xdd); /*FSTP ST[reg][EBP]*/
addbyte(0x5d);
addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]));
block_current = block_current;
}
else
{
addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x8b); /*MOV EBX, TOP*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2074,9 +2174,8 @@ static void FP_LOAD_S()
addbyte(0x83); /*AND EBX, 7*/ addbyte(0x83); /*AND EBX, 7*/
addbyte(0xe3); addbyte(0xe3);
addbyte(7); addbyte(7);
addbyte(0x83); /*CMP EAX, 0*/ addbyte(0x85); /*TEST EAX, EAX*/
addbyte(0xf8); addbyte(0xc0);
addbyte(0);
addbyte(0x89); /*MOV TOP, EBX*/ addbyte(0x89); /*MOV TOP, EBX*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2089,9 +2188,31 @@ static void FP_LOAD_S()
addbyte(0x44); addbyte(0x44);
addbyte(0x1d); addbyte(0x1d);
addbyte(cpu_state_offset(tag[0])); addbyte(cpu_state_offset(tag[0]));
}
} }
static void FP_LOAD_D() static void FP_LOAD_D()
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0x89); /*MOV ST[reg][EBP], EAX*/
addbyte(0x45);
addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]));
addbyte(0x09); /*OR EAX, EDX*/
addbyte(0xd0);
addbyte(0x89); /*MOV ST[reg][EBP]+4, EDX*/
addbyte(0x55);
addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]) + 4);
addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/
addbyte(0x45);
addbyte(cpu_state_offset(TOP));
addbyte((cpu_state.TOP - 1) & 7);
addbyte(0x0f); /*SETE tag[reg][EBP]*/
addbyte(0x94);
addbyte(0x45);
addbyte(cpu_state_offset(tag[(cpu_state.TOP - 1) & 7]));
}
else
{
addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x8b); /*MOV EBX, TOP*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2128,9 +2249,36 @@ static void FP_LOAD_D()
addbyte(0x44); addbyte(0x44);
addbyte(0x1d); addbyte(0x1d);
addbyte(cpu_state_offset(tag[0])); addbyte(cpu_state_offset(tag[0]));
}
} }
static void FP_LOAD_IW() static void FP_LOAD_IW()
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0x66); /*MOV [ESP], AX*/
addbyte(0x89);
addbyte(0x04);
addbyte(0x24);
addbyte(0x66); /*TEST AX, AX*/
addbyte(0x85);
addbyte(0xc0);
addbyte(0xdf); /*FILDw [ESP]*/
addbyte(0x04);
addbyte(0x24);
addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/
addbyte(0x45);
addbyte(cpu_state_offset(TOP));
addbyte((cpu_state.TOP - 1) & 7);
addbyte(0x0f); /*SETE tag[reg][EBP]*/
addbyte(0x94);
addbyte(0x45);
addbyte(cpu_state_offset(tag[(cpu_state.TOP - 1) & 7]));
addbyte(0xdd); /*FSTP ST[reg][EBP]*/
addbyte(0x5d);
addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]));
}
else
{
addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x8b); /*MOV EBX, TOP*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2161,9 +2309,34 @@ static void FP_LOAD_IW()
addbyte(0x44); addbyte(0x44);
addbyte(0x1d); addbyte(0x1d);
addbyte(cpu_state_offset(tag[0])); addbyte(cpu_state_offset(tag[0]));
}
} }
static void FP_LOAD_IL() static void FP_LOAD_IL()
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0x89); /*MOV [ESP], EAX*/
addbyte(0x04);
addbyte(0x24);
addbyte(0x85); /*TEST EAX, EAX*/
addbyte(0xc0);
addbyte(0xdb); /*FILDl [ESP]*/
addbyte(0x04);
addbyte(0x24);
addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/
addbyte(0x45);
addbyte(cpu_state_offset(TOP));
addbyte((cpu_state.TOP - 1) & 7);
addbyte(0x0f); /*SETE tag[reg][EBP]*/
addbyte(0x94);
addbyte(0x45);
addbyte(cpu_state_offset(tag[(cpu_state.TOP - 1) & 7]));
addbyte(0xdd); /*FSTP ST[reg][EBP]*/
addbyte(0x5d);
addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]));
}
else
{
addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x8b); /*MOV EBX, TOP*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2194,9 +2367,41 @@ static void FP_LOAD_IL()
addbyte(0x44); addbyte(0x44);
addbyte(0x1d); addbyte(0x1d);
addbyte(cpu_state_offset(tag[0])); addbyte(cpu_state_offset(tag[0]));
}
} }
static void FP_LOAD_IQ() static void FP_LOAD_IQ()
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0x89); /*MOV MM[reg][EBP], EAX*/
addbyte(0x45);
addbyte(cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q));
addbyte(0x09); /*OR EAX, EDX*/
addbyte(0xd0);
addbyte(0x89); /*MOV MM[reg][EBP]+4, EDX*/
addbyte(0x55);
addbyte(cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q) + 4);
addbyte(0x0f); /*SETE AL*/
addbyte(0x94);
addbyte(0xc0);
addbyte(0xdf); /*FILDq MM[reg][EBP]*/
addbyte(0x6d);
addbyte(cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q));
addbyte(0x0c); /*OR AL, TAG_UINT64*/
addbyte(TAG_UINT64);
addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/
addbyte(0x45);
addbyte(cpu_state_offset(TOP));
addbyte((cpu_state.TOP - 1) & 7);
addbyte(0x88); /*MOV tag[reg][EBP], AL*/
addbyte(0x45);
addbyte(cpu_state_offset(tag[(cpu_state.TOP - 1) & 7]));
addbyte(0xdd); /*FSTP ST[reg][EBP]*/
addbyte(0x5d);
addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]));
}
else
{
addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x8b); /*MOV EBX, TOP*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2239,10 +2444,19 @@ static void FP_LOAD_IQ()
addbyte(0x44); addbyte(0x44);
addbyte(0x1d); addbyte(0x1d);
addbyte(cpu_state_offset(tag[0])); addbyte(cpu_state_offset(tag[0]));
}
} }
static int FP_LOAD_REG(int reg) static int FP_LOAD_REG(int reg)
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0xdd); /*FLD ST[reg][EBP]*/
addbyte(0x45);
addbyte(cpu_state_offset(ST[(cpu_state.TOP + reg) & 7]));
}
else
{
addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x8b); /*MOV EBX, TOP*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2259,6 +2473,7 @@ static int FP_LOAD_REG(int reg)
addbyte(0x44); addbyte(0x44);
addbyte(0xdd); addbyte(0xdd);
addbyte(cpu_state_offset(ST)); addbyte(cpu_state_offset(ST));
}
addbyte(0xd9); /*FSTP [ESP]*/ addbyte(0xd9); /*FSTP [ESP]*/
addbyte(0x1c); addbyte(0x1c);
addbyte(0x24); addbyte(0x24);
@ -2271,6 +2486,14 @@ static int FP_LOAD_REG(int reg)
static void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) static void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2)
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0xdd); /*FLD ST[reg][EBP]*/
addbyte(0x45);
addbyte(cpu_state_offset(ST[(cpu_state.TOP + reg) & 7]));
}
else
{
addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x8b); /*MOV EBX, TOP*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2287,6 +2510,7 @@ static void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2)
addbyte(0x44); addbyte(0x44);
addbyte(0xdd); addbyte(0xdd);
addbyte(cpu_state_offset(ST)); addbyte(cpu_state_offset(ST));
}
addbyte(0xdd); /*FSTP [ESP]*/ addbyte(0xdd); /*FSTP [ESP]*/
addbyte(0x1c); addbyte(0x1c);
addbyte(0x24); addbyte(0x24);
@ -2542,6 +2766,19 @@ static void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2)
static void FP_POP() static void FP_POP()
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0xc6); /*MOVB tag[0][EBP], 3*/
addbyte(0x45);
addbyte(cpu_state_offset(tag[cpu_state.TOP]));
addbyte(3);
addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/
addbyte(0x45);
addbyte(cpu_state_offset(TOP));
addbyte((cpu_state.TOP + 1) & 7);
}
else
{
addbyte(0x8b); /*MOV EAX, TOP*/ addbyte(0x8b); /*MOV EAX, TOP*/
addbyte(0x45); addbyte(0x45);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2557,6 +2794,7 @@ static void FP_POP()
addbyte(0x88); /*MOV TOP, AL*/ addbyte(0x88); /*MOV TOP, AL*/
addbyte(0x45); addbyte(0x45);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
}
} }
#define FPU_ADD 0x00 #define FPU_ADD 0x00
@ -2568,6 +2806,27 @@ static void FP_POP()
static void FP_OP_S(int op) static void FP_OP_S(int op)
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0x89); /*MOV [ESP], EAX*/
addbyte(0x04);
addbyte(0x24);
addbyte(0xdd); /*FLD ST[dst][EBP]*/
addbyte(0x45);
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/
addbyte(0x65);
addbyte(cpu_state_offset(tag[cpu_state.TOP]));
addbyte(~TAG_UINT64);
addbyte(0xd8); /*FADD [ESP]*/
addbyte(0x04 | op);
addbyte(0x24);
addbyte(0xdd); /*FSTP ST[dst][EBP]*/
addbyte(0x5d);
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
}
else
{
addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x8b); /*MOV EBX, TOP*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2590,9 +2849,70 @@ static void FP_OP_S(int op)
addbyte(0x5c); addbyte(0x5c);
addbyte(0xdd); addbyte(0xdd);
addbyte(cpu_state_offset(ST)); addbyte(cpu_state_offset(ST));
}
} }
static void FP_OP_D(int op) static void FP_OP_D(int op)
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0x89); /*MOV [ESP], EAX*/
addbyte(0x04);
addbyte(0x24);
addbyte(0x89); /*MOV [ESP+4], EDX*/
addbyte(0x54);
addbyte(0x24);
addbyte(0x04);
if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD)
{
addbyte(0x9b); /*FSTCW [ESP+8]*/
addbyte(0xd9);
addbyte(0x7c);
addbyte(0x24);
addbyte(0x08);
addbyte(0x66); /*MOV AX, [ESP+8]*/
addbyte(0x8b);
addbyte(0x44);
addbyte(0x24);
addbyte(0x08);
addbyte(0x66); /*AND AX, ~(3 << 10)*/
addbyte(0x25);
addword(~(3 << 10));
addbyte(0x66); /*OR AX, npxc & (3 << 10)*/
addbyte(0x0d);
addword(cpu_state.npxc & (3 << 10));
addbyte(0x66); /*MOV [ESP+12], AX*/
addbyte(0x89);
addbyte(0x44);
addbyte(0x24);
addbyte(0x0c);
addbyte(0xd9); /*FLDCW [ESP+12]*/
addbyte(0x6c);
addbyte(0x24);
addbyte(0x0c);
}
addbyte(0xdd); /*FLD ST[dst][EBP]*/
addbyte(0x45);
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/
addbyte(0x65);
addbyte(cpu_state_offset(tag[cpu_state.TOP]));
addbyte(~TAG_UINT64);
addbyte(0xdc); /*FADD [ESP]*/
addbyte(0x04 | op);
addbyte(0x24);
addbyte(0xdd); /*FSTP ST[dst][EBP]*/
addbyte(0x5d);
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD)
{
addbyte(0xd9); /*FLDCW [ESP+8]*/
addbyte(0x6c);
addbyte(0x24);
addbyte(0x08);
}
}
else
{
addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x8b); /*MOV EBX, TOP*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2654,9 +2974,32 @@ static void FP_OP_D(int op)
addbyte(0x24); addbyte(0x24);
addbyte(0x08); addbyte(0x08);
} }
}
} }
static void FP_OP_IW(int op) static void FP_OP_IW(int op)
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0x66); /*MOV [ESP], AX*/
addbyte(0x89);
addbyte(0x04);
addbyte(0x24);
addbyte(0xdd); /*FLD ST[0][EBP]*/
addbyte(0x45);
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/
addbyte(0x65);
addbyte(cpu_state_offset(tag[cpu_state.TOP]));
addbyte(~TAG_UINT64);
addbyte(0xde); /*FADD [ESP]*/
addbyte(0x04 | op);
addbyte(0x24);
addbyte(0xdd); /*FSTP ST[0][EBP]*/
addbyte(0x5d);
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
}
else
{
addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x8b); /*MOV EBX, TOP*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2679,9 +3022,31 @@ static void FP_OP_IW(int op)
addbyte(0x5c); addbyte(0x5c);
addbyte(0xdd); addbyte(0xdd);
addbyte(cpu_state_offset(ST)); addbyte(cpu_state_offset(ST));
}
} }
static void FP_OP_IL(int op) static void FP_OP_IL(int op)
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0x89); /*MOV [ESP], EAX*/
addbyte(0x04);
addbyte(0x24);
addbyte(0xdd); /*FLD ST[0][EBP]*/
addbyte(0x45);
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/
addbyte(0x65);
addbyte(cpu_state_offset(tag[cpu_state.TOP]));
addbyte(~TAG_UINT64);
addbyte(0xda); /*FADD [ESP]*/
addbyte(0x04 | op);
addbyte(0x24);
addbyte(0xdd); /*FSTP ST[0][EBP]*/
addbyte(0x5d);
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
}
else
{
addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x8b); /*MOV EBX, TOP*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2704,9 +3069,35 @@ static void FP_OP_IL(int op)
addbyte(0x5c); addbyte(0x5c);
addbyte(0xdd); addbyte(0xdd);
addbyte(cpu_state_offset(ST)); addbyte(cpu_state_offset(ST));
}
} }
static void FP_OP_IQ(int op) static void FP_OP_IQ(int op)
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0x89); /*MOV [ESP], EAX*/
addbyte(0x04);
addbyte(0x24);
addbyte(0x89); /*MOV [ESP+4], EDX*/
addbyte(0x54);
addbyte(0x24);
addbyte(0x04);
addbyte(0xdd); /*FLD ST[0][EBP]*/
addbyte(0x45);
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/
addbyte(0x65);
addbyte(cpu_state_offset(tag[cpu_state.TOP]));
addbyte(~TAG_UINT64);
addbyte(0xdc); /*FADD [ESP]*/
addbyte(0x04 | op);
addbyte(0x24);
addbyte(0xdd); /*FSTP ST[0][EBP]*/
addbyte(0x5d);
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
}
else
{
addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x8b); /*MOV EBX, TOP*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2733,6 +3124,7 @@ static void FP_OP_IQ(int op)
addbyte(0x5c); addbyte(0x5c);
addbyte(0xdd); addbyte(0xdd);
addbyte(cpu_state_offset(ST)); addbyte(cpu_state_offset(ST));
}
} }
#define C0 (1<<8) #define C0 (1<<8)
@ -2742,6 +3134,38 @@ static void FP_OP_IQ(int op)
static void FP_COMPARE_S() static void FP_COMPARE_S()
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0x89); /*MOV [ESP], EAX*/
addbyte(0x04);
addbyte(0x24);
addbyte(0xdd); /*FLD ST[0][EBP]*/
addbyte(0x45);
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
addbyte(0x8a); /*MOV BL, [npxs+1]*/
addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1);
addbyte(0xdb); /*FCLEX*/
addbyte(0xe2);
addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/
addbyte(0xe3);
addbyte((~(C0|C2|C3)) >> 8);
addbyte(0xd8); /*FCOMP [ESP]*/
addbyte(0x04 | 0x18);
addbyte(0x24);
addbyte(0xdf); /*FSTSW AX*/
addbyte(0xe0);
addbyte(0x80); /*AND AH, (C0|C2|C3)*/
addbyte(0xe4);
addbyte((C0|C2|C3) >> 8);
addbyte(0x08); /*OR BL, AH*/
addbyte(0xe3);
addbyte(0x88); /*MOV [npxs+1], BL*/
addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1);
}
else
{
addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x8b); /*MOV EBX, TOP*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2773,9 +3197,46 @@ static void FP_COMPARE_S()
addbyte(0x88); /*MOV [npxs+1], BL*/ addbyte(0x88); /*MOV [npxs+1], BL*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1); addbyte(cpu_state_offset(npxs) + 1);
}
} }
static void FP_COMPARE_D() static void FP_COMPARE_D()
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0x89); /*MOV [ESP], EAX*/
addbyte(0x04);
addbyte(0x24);
addbyte(0x89); /*MOV [ESP+4], EDX*/
addbyte(0x54);
addbyte(0x24);
addbyte(0x04);
addbyte(0xdd); /*FLD ST[0][EBP]*/
addbyte(0x45);
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
addbyte(0x8a); /*MOV BL, [npxs+1]*/
addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1);
addbyte(0xdb); /*FCLEX*/
addbyte(0xe2);
addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/
addbyte(0xe3);
addbyte((~(C0|C2|C3)) >> 8);
addbyte(0xdc); /*FCOMP [ESP]*/
addbyte(0x04 | 0x18);
addbyte(0x24);
addbyte(0xdf); /*FSTSW AX*/
addbyte(0xe0);
addbyte(0x80); /*AND AH, (C0|C2|C3)*/
addbyte(0xe4);
addbyte((C0|C2|C3) >> 8);
addbyte(0x08); /*OR BL, AH*/
addbyte(0xe3);
addbyte(0x88); /*MOV [npxs+1], BL*/
addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1);
}
else
{
addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x8b); /*MOV EBX, TOP*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2811,9 +3272,43 @@ static void FP_COMPARE_D()
addbyte(0x88); /*MOV [npxs+1], BL*/ addbyte(0x88); /*MOV [npxs+1], BL*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1); addbyte(cpu_state_offset(npxs) + 1);
}
} }
static void FP_COMPARE_IW() static void FP_COMPARE_IW()
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0x66); /*MOV [ESP], AX*/
addbyte(0x89);
addbyte(0x04);
addbyte(0x24);
addbyte(0xdd); /*FLD ST[0][EBP]*/
addbyte(0x45);
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
addbyte(0x8a); /*MOV BL, [npxs+1]*/
addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1);
addbyte(0xdb); /*FCLEX*/
addbyte(0xe2);
addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/
addbyte(0xe3);
addbyte((~(C0|C2|C3)) >> 8);
addbyte(0xde); /*FCOMP [ESP]*/
addbyte(0x04 | 0x18);
addbyte(0x24);
addbyte(0xdf); /*FSTSW AX*/
addbyte(0xe0);
addbyte(0x80); /*AND AH, (C0|C2|C3)*/
addbyte(0xe4);
addbyte((C0|C2|C3) >> 8);
addbyte(0x08); /*OR BL, AH*/
addbyte(0xe3);
addbyte(0x88); /*MOV [npxs+1], BL*/
addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1);
}
else
{
addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x8b); /*MOV EBX, TOP*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2845,9 +3340,42 @@ static void FP_COMPARE_IW()
addbyte(0x88); /*MOV [npxs+1], BL*/ addbyte(0x88); /*MOV [npxs+1], BL*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1); addbyte(cpu_state_offset(npxs) + 1);
}
} }
static void FP_COMPARE_IL() static void FP_COMPARE_IL()
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0x89); /*MOV [ESP], EAX*/
addbyte(0x04);
addbyte(0x24);
addbyte(0xdd); /*FLD ST[0][EBP]*/
addbyte(0x45);
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
addbyte(0x8a); /*MOV BL, [npxs+1]*/
addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1);
addbyte(0xdb); /*FCLEX*/
addbyte(0xe2);
addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/
addbyte(0xe3);
addbyte((~(C0|C2|C3)) >> 8);
addbyte(0xda); /*FCOMP [ESP]*/
addbyte(0x04 | 0x18);
addbyte(0x24);
addbyte(0xdf); /*FSTSW AX*/
addbyte(0xe0);
addbyte(0x80); /*AND AH, (C0|C2|C3)*/
addbyte(0xe4);
addbyte((C0|C2|C3) >> 8);
addbyte(0x08); /*OR BL, AH*/
addbyte(0xe3);
addbyte(0x88); /*MOV [npxs+1], BL*/
addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1);
}
else
{
addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x8b); /*MOV EBX, TOP*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
@ -2879,15 +3407,32 @@ static void FP_COMPARE_IL()
addbyte(0x88); /*MOV [npxs+1], BL*/ addbyte(0x88); /*MOV [npxs+1], BL*/
addbyte(0x5d); addbyte(0x5d);
addbyte(cpu_state_offset(npxs) + 1); addbyte(cpu_state_offset(npxs) + 1);
}
} }
static void FP_OP_REG(int op, int dst, int src) static void FP_OP_REG(int op, int dst, int src)
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0xdd); /*FLD ST[dst][EBP]*/
addbyte(0x45);
addbyte(cpu_state_offset(ST[(cpu_state.TOP + dst) & 7]));
addbyte(0xdc); /*FADD ST[src][EBP]*/
addbyte(0x45 | op);
addbyte(cpu_state_offset(ST[(cpu_state.TOP + src) & 7]));
addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/
addbyte(0x65);
addbyte(cpu_state_offset(tag[(cpu_state.TOP + dst) & 7]));
addbyte(~TAG_UINT64);
addbyte(0xdd); /*FSTP ST[dst][EBP]*/
addbyte(0x5d);
addbyte(cpu_state_offset(ST[(cpu_state.TOP + dst) & 7]));
}
else
{
addbyte(0x8b); /*MOV EAX, TOP*/ addbyte(0x8b); /*MOV EAX, TOP*/
addbyte(0x45); addbyte(0x45);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
// addbyte(0xbe); /*MOVL ESI, ST*/
// addlong((uintptr_t)cpu_state.ST);
addbyte(0x89); /*MOV EBX, EAX*/ addbyte(0x89); /*MOV EBX, EAX*/
addbyte(0xc3); addbyte(0xc3);
if (src || dst) if (src || dst)
@ -2940,15 +3485,43 @@ static void FP_OP_REG(int op, int dst, int src)
addbyte(0xc5); addbyte(0xc5);
addbyte(cpu_state_offset(ST)); addbyte(cpu_state_offset(ST));
} }
}
} }
static void FP_COMPARE_REG(int dst, int src) static void FP_COMPARE_REG(int dst, int src)
{ {
if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP)
{
addbyte(0x8a); /*MOV CL, [npxs+1]*/
addbyte(0x4d);
addbyte(cpu_state_offset(npxs) + 1);
addbyte(0xdb); /*FCLEX*/
addbyte(0xe2);
addbyte(0xdd); /*FLD ST[dst][EBP]*/
addbyte(0x45);
addbyte(cpu_state_offset(ST[(cpu_state.TOP + dst) & 7]));
addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/
addbyte(0xe1);
addbyte((~(C0|C2|C3)) >> 8);
addbyte(0xdc); /*FCOMP ST[src][EBP]*/
addbyte(0x5d);
addbyte(cpu_state_offset(ST[(cpu_state.TOP + src) & 7]));
addbyte(0xdf); /*FSTSW AX*/
addbyte(0xe0);
addbyte(0x80); /*AND AH, (C0|C2|C3)*/
addbyte(0xe4);
addbyte((C0|C2|C3) >> 8);
addbyte(0x08); /*OR CL, AH*/
addbyte(0xe1);
addbyte(0x88); /*MOV [npxs+1], CL*/
addbyte(0x4d);
addbyte(cpu_state_offset(npxs) + 1);
}
else
{
addbyte(0x8b); /*MOV EAX, TOP*/ addbyte(0x8b); /*MOV EAX, TOP*/
addbyte(0x45); addbyte(0x45);
addbyte(cpu_state_offset(TOP)); addbyte(cpu_state_offset(TOP));
// addbyte(0xbe); /*MOVL ESI, ST*/
// addlong((uintptr_t)cpu_state.ST);
addbyte(0x89); /*MOV EBX, EAX*/ addbyte(0x89); /*MOV EBX, EAX*/
addbyte(0xc3); addbyte(0xc3);
if (src || dst) if (src || dst)
@ -3003,6 +3576,7 @@ static void FP_COMPARE_REG(int dst, int src)
addbyte(0x88); /*MOV [npxs+1], CL*/ addbyte(0x88); /*MOV [npxs+1], CL*/
addbyte(0x4d); addbyte(0x4d);
addbyte(cpu_state_offset(npxs) + 1); addbyte(cpu_state_offset(npxs) + 1);
}
} }
static int ZERO_EXTEND_W_B(int reg) static int ZERO_EXTEND_W_B(int reg)

View file

@ -281,6 +281,7 @@ void codegen_block_init(uint32_t phys_addr)
block->next = block->prev = NULL; block->next = block->prev = NULL;
block->next_2 = block->prev_2 = NULL; block->next_2 = block->prev_2 = NULL;
block->page_mask = 0; block->page_mask = 0;
block->flags = 0;
block->was_recompiled = 0; block->was_recompiled = 0;
@ -1005,6 +1006,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
over = 1; over = 1;
pc_off = -1; pc_off = -1;
test_modrm = 0; test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break; break;
case 0xd9: case 0xd9:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16;
@ -1013,6 +1015,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
over = 1; over = 1;
pc_off = -1; pc_off = -1;
test_modrm = 0; test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break; break;
case 0xda: case 0xda:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16;
@ -1021,6 +1024,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
over = 1; over = 1;
pc_off = -1; pc_off = -1;
test_modrm = 0; test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break; break;
case 0xdb: case 0xdb:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16;
@ -1029,6 +1033,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
over = 1; over = 1;
pc_off = -1; pc_off = -1;
test_modrm = 0; test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break; break;
case 0xdc: case 0xdc:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16;
@ -1038,6 +1043,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
over = 1; over = 1;
pc_off = -1; pc_off = -1;
test_modrm = 0; test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break; break;
case 0xdd: case 0xdd:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16;
@ -1046,6 +1052,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
over = 1; over = 1;
pc_off = -1; pc_off = -1;
test_modrm = 0; test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break; break;
case 0xde: case 0xde:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16;
@ -1054,6 +1061,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
over = 1; over = 1;
pc_off = -1; pc_off = -1;
test_modrm = 0; test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break; break;
case 0xdf: case 0xdf:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16;
@ -1062,6 +1070,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
over = 1; over = 1;
pc_off = -1; pc_off = -1;
test_modrm = 0; test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break; break;
case 0xf0: /*LOCK*/ case 0xf0: /*LOCK*/

View file

@ -281,6 +281,7 @@ void codegen_block_init(uint32_t phys_addr)
block->next = block->prev = NULL; block->next = block->prev = NULL;
block->next_2 = block->prev_2 = NULL; block->next_2 = block->prev_2 = NULL;
block->page_mask = 0; block->page_mask = 0;
block->flags = CODEBLOCK_STATIC_TOP;
block->was_recompiled = 0; block->was_recompiled = 0;
@ -359,6 +360,7 @@ void codegen_block_start_recompile(codeblock_t *block)
_ds.checked = _es.checked = _fs.checked = _gs.checked = (cr0 & 1) ? 0 : 1; _ds.checked = _es.checked = _fs.checked = _gs.checked = (cr0 & 1) ? 0 : 1;
block->TOP = cpu_state.TOP;
block->was_recompiled = 1; block->was_recompiled = 1;
} }
@ -484,6 +486,9 @@ void codegen_block_end_recompile(codeblock_t *block)
codegen_block_generate_end_mask(); codegen_block_generate_end_mask();
add_to_block_list(block); add_to_block_list(block);
// pclog("End block %i\n", block_num); // pclog("End block %i\n", block_num);
if (!(block->flags & CODEBLOCK_HAS_FPU))
block->flags &= ~CODEBLOCK_STATIC_TOP;
} }
void codegen_flush() void codegen_flush()
@ -821,6 +826,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
over = 1; over = 1;
pc_off = -1; pc_off = -1;
test_modrm = 0; test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break; break;
case 0xd9: case 0xd9:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16;
@ -829,6 +835,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
over = 1; over = 1;
pc_off = -1; pc_off = -1;
test_modrm = 0; test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break; break;
case 0xda: case 0xda:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16;
@ -837,6 +844,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
over = 1; over = 1;
pc_off = -1; pc_off = -1;
test_modrm = 0; test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break; break;
case 0xdb: case 0xdb:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16;
@ -845,6 +853,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
over = 1; over = 1;
pc_off = -1; pc_off = -1;
test_modrm = 0; test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break; break;
case 0xdc: case 0xdc:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16;
@ -854,6 +863,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
over = 1; over = 1;
pc_off = -1; pc_off = -1;
test_modrm = 0; test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break; break;
case 0xdd: case 0xdd:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16;
@ -862,6 +872,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
over = 1; over = 1;
pc_off = -1; pc_off = -1;
test_modrm = 0; test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break; break;
case 0xde: case 0xde:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16;
@ -870,6 +881,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
over = 1; over = 1;
pc_off = -1; pc_off = -1;
test_modrm = 0; test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break; break;
case 0xdf: case 0xdf:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16;
@ -878,6 +890,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
over = 1; over = 1;
pc_off = -1; pc_off = -1;
test_modrm = 0; test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break; break;
case 0xf0: /*LOCK*/ case 0xf0: /*LOCK*/