diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-04-24 15:34:54 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-04-24 15:34:54 +0200 |
| commit | 2a79b604546769e600600f3d85a684641b0bca28 (patch) | |
| tree | e061157fd647be5248117361a21db702d5026791 /src/emu | |
| parent | db32e498790a13f3dc0a78748d47530cf8404015 (diff) | |
| download | box64-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.c | 4 | ||||
| -rw-r--r-- | src/emu/x64emu_private.h | 2 | ||||
| -rw-r--r-- | src/emu/x64rund9.c | 5 | ||||
| -rw-r--r-- | src/emu/x64rundd.c | 2 | ||||
| -rw-r--r-- | src/emu/x64test.c | 6 | ||||
| -rw-r--r-- | src/emu/x87emu_private.c | 36 | ||||
| -rw-r--r-- | src/emu/x87emu_private.h | 17 |
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; |