about summary refs log tree commit diff stats
path: root/src/emu
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-04-24 15:34:54 +0200
committerptitSeb <sebastien.chev@gmail.com>2024-04-24 15:34:54 +0200
commit2a79b604546769e600600f3d85a684641b0bca28 (patch)
treee061157fd647be5248117361a21db702d5026791 /src/emu
parentdb32e498790a13f3dc0a78748d47530cf8404015 (diff)
downloadbox64-2a79b604546769e600600f3d85a684641b0bca28.tar.gz
box64-2a79b604546769e600600f3d85a684641b0bca28.zip
Changed x87 way of handling FFREE opcode ([DYNAREC] too, improving x87 robustness overall)
Diffstat (limited to 'src/emu')
-rw-r--r--src/emu/x64emu.c4
-rw-r--r--src/emu/x64emu_private.h2
-rw-r--r--src/emu/x64rund9.c5
-rw-r--r--src/emu/x64rundd.c2
-rw-r--r--src/emu/x64test.c6
-rw-r--r--src/emu/x87emu_private.c36
-rw-r--r--src/emu/x87emu_private.h17
7 files changed, 40 insertions, 32 deletions
diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c
index 69aed8c1..7d54d651 100644
--- a/src/emu/x64emu.c
+++ b/src/emu/x64emu.c
@@ -234,7 +234,7 @@ void CloneEmu(x64emu_t *newemu, const x64emu_t* emu)
 	memcpy(newemu->mmx, emu->mmx, sizeof(emu->mmx));
     memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
     memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
-	memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs));
+    newemu->fpu_tags = emu->fpu_tags;
 	newemu->cw = emu->cw;
 	newemu->sw = emu->sw;
 	newemu->top = emu->top;
@@ -270,7 +270,7 @@ void CopyEmu(x64emu_t *newemu, const x64emu_t* emu)
     memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm));
     memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
     memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
-	memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs));
+    newemu->fpu_tags = emu->fpu_tags;
 	newemu->cw = emu->cw;
 	newemu->sw = emu->sw;
 	newemu->top = emu->top;
diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h
index 90c9b7b0..7ae9e1bd 100644
--- a/src/emu/x64emu_private.h
+++ b/src/emu/x64emu_private.h
@@ -76,7 +76,7 @@ typedef struct x64emu_s {
     #endif
     fpu_ld_t    fpu_ld[8]; // for long double emulation / 80bits fld fst
     fpu_ll_t    fpu_ll[8]; // for 64bits fild / fist sequence
-	fpu_p_reg_t p_regs[8];
+    uint64_t    fpu_tags;   // tags for the x87 regs, stacked, only on a 16bits anyway
     // old ip
     uintptr_t   old_ip;
     // deferred flags
diff --git a/src/emu/x64rund9.c b/src/emu/x64rund9.c
index 2cc8cdce..015dfa07 100644
--- a/src/emu/x64rund9.c
+++ b/src/emu/x64rund9.c
@@ -192,7 +192,10 @@ uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr)
             emu->top=(emu->top-1)&7;    // this will probably break a few things

             break;

         case 0xF7:  /* FINCSTP */

-            emu->top=(emu->top+1)&7;    // this will probably break a few things

+            if(emu->fpu_tags&0b11)

+                fpu_do_pop(emu);

+            else

+                emu->top=(emu->top+1)&7;    // this will probably break a few things

             break;

         case 0xF9:  /* FYL2XP1 */

             ST(1).d *= log2(ST0.d + 1.0);

diff --git a/src/emu/x64rundd.c b/src/emu/x64rundd.c
index 35b439fe..a62c9254 100644
--- a/src/emu/x64rundd.c
+++ b/src/emu/x64rundd.c
@@ -45,7 +45,7 @@ uintptr_t RunDD(x64emu_t *emu, rex_t rex, uintptr_t addr)
         case 0xC5:

         case 0xC6:

         case 0xC7:

-            fpu_do_free(emu, nextop-0xC0);

+            fpu_do_free(emu, nextop&7);

             break;

 

         case 0xD0:  /* FST ST0, STx */

diff --git a/src/emu/x64test.c b/src/emu/x64test.c
index f1294466..447cd384 100644
--- a/src/emu/x64test.c
+++ b/src/emu/x64test.c
@@ -82,10 +82,10 @@ void x64test_check(x64emu_t* ref, uintptr_t ip)
     }
     //memcpy(ref->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
     //memcpy(ref->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
-	/*if(ref->p_regs != emu->p_regs) {
+	if(ref->fpu_tags != emu->fpu_tags) {
         BANNER;
-        printf_log(LOG_NONE, "X87 PREG: %x | %x\n", ref->p_regs, emu->p_regs);
-    }*/
+        printf_log(LOG_NONE, "X87 TAGS: %x | %x\n", ref->fpu_tags, emu->fpu_tags);
+    }
 	if(ref->cw.x16 != emu->cw.x16) {
         BANNER;
         printf_log(LOG_NONE, "X87 CW: %x | %x\n", ref->cw.x16, emu->cw.x16);
diff --git a/src/emu/x87emu_private.c b/src/emu/x87emu_private.c
index 67573c37..0ad3db8c 100644
--- a/src/emu/x87emu_private.c
+++ b/src/emu/x87emu_private.c
@@ -11,10 +11,10 @@
 
 void fpu_do_free(x64emu_t* emu, int i)
 {
-    emu->p_regs[(emu->top+i)&7].tag = 0b11;    // empty
+    emu->fpu_tags |= 0b11 << (i);   // empty
     // check if all empty
     for(int j=0; j<8; ++j)
-        if(emu->p_regs[j].tag != 0b11)
+        if(emu->fpu_tags != TAGS_EMPTY)
             return;
     emu->fpu_stack = 0;
 }
@@ -27,8 +27,7 @@ void reset_fpu(x64emu_t* emu)
     emu->sw.x16 = 0x0000;
     emu->top = 0;
     emu->fpu_stack = 0;
-    for(int i=0; i<8; ++i)
-        emu->p_regs[i].tag = 0b11;  // STx is empty
+    emu->fpu_tags = TAGS_EMPTY;
 }
 
 void fpu_fbst(x64emu_t* emu, uint8_t* d) {
@@ -258,9 +257,7 @@ void fpu_loadenv(x64emu_t* emu, char* p, int b16)
     p+=(b16)?2:4;
     // tagword: 2bits*8
     // tags... (only full = 0b11 / free = 0b00)
-    uint16_t tags = *(uint16_t*)p;
-    for(int i=0; i<8; ++i)
-        emu->p_regs[i].tag = (tags>>(i*2))&0b11;
+    emu->fpu_tags = *(uint16_t*)p;
     // intruction pointer: 16bits
     // data (operand) pointer: 16bits
     // last opcode: 11bits save: 16bits restaured (1st and 2nd opcode only)
@@ -277,10 +274,7 @@ void fpu_savenv(x64emu_t* emu, char* p, int b16)
     if(!b16) {*(uint16_t*)p = 0; p+=2;}
     // tagword: 2bits*8
     // tags...
-    uint16_t tags = 0;
-    for (int i=0; i<8; ++i)
-        tags |= (emu->p_regs[i].tag)<<(i*2);
-    *(uint16_t*)p = tags;
+    *(uint16_t*)p = emu->fpu_tags;
     // other stuff are not pushed....
 }
 
@@ -325,14 +319,14 @@ void fpu_fxsave32(x64emu_t* emu, void* ed)
     int top = emu->top&7;
     int stack = 8-top;
     if(top==0)  // check if stack is full or empty, based on tag[0]
-        stack = (emu->p_regs[0].tag)?8:0;
+        stack = (emu->fpu_tags&0b11)?8:0;
     emu->sw.f.F87_TOP = top;
     p->ControlWord = emu->cw.x16;
     p->StatusWord = emu->sw.x16;
     p->MxCsr = emu->mxcsr.x32;
     uint8_t tags = 0;
     for (int i=0; i<8; ++i)
-        tags |= ((emu->p_regs[i].tag)<<(i*2)==0b11)?0:1;
+        tags |= ((emu->fpu_tags>>(i*2))&0b11)?0:1;
     p->TagWord = tags;
     p->ErrorOpcode = 0;
     p->ErrorOffset = 0;
@@ -353,15 +347,15 @@ void fpu_fxsave64(x64emu_t* emu, void* ed)
     int top = emu->top&7;
     int stack = 8-top;
     if(top==0)  // check if stack is full or empty, based on tag[0]
-        stack = (emu->p_regs[0].tag)?8:0;
+        stack = (emu->fpu_tags&0b11)?8:0;
     emu->sw.f.F87_TOP = top;
     p->ControlWord = emu->cw.x16;
     p->StatusWord = emu->sw.x16;
     p->MxCsr = emu->mxcsr.x32;
     uint8_t tags = 0;
     for (int i=0; i<8; ++i)
-        tags |= ((emu->p_regs[i].tag)<<(i*2)==0b11)?0:1;
-    p->TagWord = tags;
+        tags |= ((emu->fpu_tags>>(i*2))&0b11)?0:1;
+    p->TagWord = emu->fpu_tags;
     p->ErrorOpcode = 0;
     p->ErrorOffset = 0;
     p->DataOffset = 0;
@@ -382,12 +376,12 @@ void fpu_fxrstor32(x64emu_t* emu, void* ed)
         applyFlushTo0(emu);
     emu->top = emu->sw.f.F87_TOP;
     uint8_t tags = p->TagWord;
-    for(int i=0; i<8; ++i)
-        emu->p_regs[i].tag = (tags>>(i*2))?0:0b11;
+    for (int i=0; i<8; ++i)
+        tags |= ((emu->fpu_tags>>(i*2))&0b11)?0:1;
     int top = emu->top&7;
     int stack = 8-top;
     if(top==0)  // check if stack is full or empty, based on tag[0]
-        stack = (emu->p_regs[0].tag)?8:0;
+        stack = (emu->fpu_tags&0b11)?8:0;
     // copy back MMX regs...
     for(int i=0; i<8; ++i)
         memcpy((i<stack)?&ST(i):&emu->mmx[i], &p->FloatRegisters[i].q[0], sizeof(mmx87_regs_t));
@@ -406,11 +400,11 @@ void fpu_fxrstor64(x64emu_t* emu, void* ed)
     emu->top = emu->sw.f.F87_TOP;
     uint8_t tags = p->TagWord;
     for(int i=0; i<8; ++i)
-        emu->p_regs[i].tag = (tags>>(i*2))?0:0b11;
+        emu->fpu_tags |= ((tags>>i)?0:0b11)<<(i*2);
     int top = emu->top&7;
     int stack = 8-top;
     if(top==0)  // check if stack is full or empty, based on tag[0]
-        stack = (emu->p_regs[0].tag)?8:0;
+        stack = (emu->fpu_tags&0b11)?8:0;
     // copy back MMX regs...
     for(int i=0; i<8; ++i)
         memcpy((i<stack)?&ST(i):&emu->mmx[i], &p->FloatRegisters[i].q[0], sizeof(mmx87_regs_t));
diff --git a/src/emu/x87emu_private.h b/src/emu/x87emu_private.h
index ae977133..a3c589df 100644
--- a/src/emu/x87emu_private.h
+++ b/src/emu/x87emu_private.h
@@ -15,6 +15,8 @@ typedef struct x64emu_s x64emu_t;
 #define LN2		0.69314718055994531
 #define LG2		0.3010299956639812
 
+#define TAGS_EMPTY 0b1111111111111111
+
 #define ST0 emu->x87[emu->top]
 #define ST1 emu->x87[(emu->top+1)&7]
 #define ST(a) emu->x87[(emu->top+(a))&7]
@@ -32,7 +34,8 @@ static inline void fpu_do_push(x64emu_t* emu)
     }*/
     if(emu->fpu_stack<8)
         ++emu->fpu_stack; 
-    emu->p_regs[newtop].tag = 0;    // full
+    emu->fpu_tags<<=2;  // st0 full
+    emu->fpu_tags &= TAGS_EMPTY;
     emu->top = newtop;
 }
 
@@ -47,8 +50,16 @@ static inline void fpu_do_pop(x64emu_t* emu)
     if(emu->fpu_stack>0)
         --emu->fpu_stack;
     
-    emu->p_regs[curtop].tag = 0b11;    // empty
+    emu->fpu_tags>>=2;
+    emu->fpu_tags |= 0b1100000000000000;    // top empty
     emu->top = (emu->top+1)&7;
+    // check tags
+    /*while((emu->fpu_tags&0b11) && emu->fpu_stack) {
+        --emu->fpu_stack;
+        emu->top = (emu->top+1)&7;
+        emu->fpu_tags>>=2;
+        emu->fpu_tags |= 0b1100000000000000;    // top empty
+    }*/
 }
 
 void fpu_do_free(x64emu_t* emu, int i);
@@ -128,7 +139,7 @@ static inline double fpu_round(x64emu_t* emu, double d) {
 
 static inline void fpu_fxam(x64emu_t* emu) {
     emu->sw.f.F87_C1 = (ST0.ud[1]&0x80000000)?1:0;
-    if((emu->fpu_stack<=0) || (emu->p_regs[(emu->top)&7].tag == 0b11)) {
+    if((emu->fpu_stack<=0) || (emu->fpu_tags&0b11)) {
         //Empty
         emu->sw.f.F87_C3 = 1;
         emu->sw.f.F87_C2 = 0;