diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-12-02 16:18:41 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-12-02 16:18:41 +0100 |
| commit | f2822f1a05afe63f233e172f67dcbe1f3b234551 (patch) | |
| tree | a7cd1b20140449592720816c801883f1a43bff66 /src | |
| parent | 646dd718f5f6cb8390b0507bb1d407707feb9603 (diff) | |
| download | box64-f2822f1a05afe63f233e172f67dcbe1f3b234551.tar.gz box64-f2822f1a05afe63f233e172f67dcbe1f3b234551.zip | |
[INTERPRETER] Improved some x87 opcode behaviour
Diffstat (limited to 'src')
| -rw-r--r-- | src/emu/x64rund9.c | 15 | ||||
| -rw-r--r-- | src/emu/x64rundb.c | 6 | ||||
| -rw-r--r-- | src/emu/x87emu_private.c | 35 | ||||
| -rw-r--r-- | src/emu/x87emu_private.h | 8 |
4 files changed, 36 insertions, 28 deletions
diff --git a/src/emu/x64rund9.c b/src/emu/x64rund9.c index 3c7ac142..648eb0a7 100644 --- a/src/emu/x64rund9.c +++ b/src/emu/x64rund9.c @@ -140,9 +140,20 @@ uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr, uintptr_t offs) fpu_do_pop(emu); break; case 0xF4: /* FXTRACT */ - ST0.d = frexp(ST0.d, &tmp32s); fpu_do_push(emu); - ST0.d = tmp32s; + if(isnan(ST1.d)) { + ST0.d = ST1.d; + } else if(isinf(ST1.d)) { + ST0.d = ST1.d; + ST1.d = INFINITY; + } else if(ST1.d==0.0) { + ST0.d = ST1.d; + ST1.d = -INFINITY; + } else { + // LD80bits doesn't have implicit "1" bit, so need to adjust for that + ST0.d = frexp(ST1.d, &tmp32s)*2; + ST1.d = tmp32s-1; + } break; case 0xF8: /* FPREM */ diff --git a/src/emu/x64rundb.c b/src/emu/x64rundb.c index 9fdae847..82ea43ff 100644 --- a/src/emu/x64rundb.c +++ b/src/emu/x64rundb.c @@ -172,10 +172,10 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr) break; case 7: /* FSTP tbyte */ GETET(0); - if(ST0.q!=STld(0).uref) - D2LD(&ST0.d, ED); - else + if(STld(0).uref && (ST0.q==STld(0).uref)) memcpy(ED, &STld(0).ld, 10); + else + D2LD(&ST0.d, ED); fpu_do_pop(emu); break; default: diff --git a/src/emu/x87emu_private.c b/src/emu/x87emu_private.c index 5f6bdba0..21090ce8 100644 --- a/src/emu/x87emu_private.c +++ b/src/emu/x87emu_private.c @@ -99,39 +99,31 @@ void LD2D(void* ld, void* d) val.f.ud[1] = *(uint32_t*)(char*)(ld+4); val.b = *(int16_t*)((char*)ld+8); #endif - int32_t exp64 = (((uint32_t)(val.b&0x7fff) - BIAS80) + BIAS64); - int32_t exp64final = exp64&0x7ff; // do specific value first (0, infinite...) // bit 63 is "integer part" - // bit 62 is sign if((uint32_t)(val.b&0x7fff)==0x7fff) { // infinity and nans - int t = 0; //nan - switch((val.f.ud[1]>>30)) { - case 0: if((val.f.ud[1]&(1<<29))==0) t = 1; - break; - case 2: if((val.f.ud[1]&(1<<29))==0) t = 1; - break; - } + int t = (val.f.q&0x7fffffffffffffffLL)?0:1; if(t) { // infinite - result.d = HUGE_VAL; - } else { // NaN - result.ud[1] = 0x7ff << 20; + result.ud[1] = (val.b>>4) << 20; result.ud[0] = 0; + } else { // NaN + result.ud[1] = (val.b>>4) << 20 | ((val.f.q>>(63-20))&0x000fffff); + result.ud[0] = (val.f.q>>(63-56))&0xffffffff; + if(!(result.q&0x000fffffffffffffLL)) + result.q |= 1; } - if(val.b&0x8000) - result.ud[1] |= 0x80000000; *(uint64_t*)d = result.q; return; } + int32_t exp64 = (((uint32_t)(val.b&0x7fff) - BIAS80) + BIAS64); + int32_t exp64final = exp64&0x7ff; if(((uint32_t)(val.b&0x7fff)==0) || (exp64<-1074)) { //if(val.f.q==0) // zero //if(val.f.q!=0) // denormal, but that's to small value for double - uint64_t r = 0; - if(val.b&0x8000) - r |= 0x8000000000000000L; + uint64_t r = (val.b&0x8000)?0x8000000000000000LL:0LL; *(uint64_t*)d = r; return; } @@ -184,10 +176,7 @@ void D2LD(void* d, void* ld) if((s.q&0x7fffffffffffffffL)==0) { // zero... val.f.q = 0; - if(s.ud[1]&0x8000) - val.b = 0x8000; - else - val.b = 0; + val.b = (s.ud[1]&0x80000000)?0x8000:0; memcpy(ld, &val, 10); return; } @@ -203,7 +192,7 @@ void D2LD(void* d, void* ld) if(mant80==0x0) mant80final = 0x8000000000000000L; //infinity else - mant80final = 0xc000000000000000L; //(quiet)NaN + mant80final |= 0x8000000000000000L; //(quiet)NaN } else { if(exp80!=0){ mant80final |= 0x8000000000000000L; diff --git a/src/emu/x87emu_private.h b/src/emu/x87emu_private.h index 74758acf..e3f0d233 100644 --- a/src/emu/x87emu_private.h +++ b/src/emu/x87emu_private.h @@ -73,6 +73,10 @@ static inline void fpu_fcom(x64emu_t* emu, double b) emu->sw.f.F87_C0 = 1; emu->sw.f.F87_C2 = 1; emu->sw.f.F87_C3 = 1; + } else if ((b==-INFINITY) || (ST0.d==INFINITY)) { + emu->sw.f.F87_C0 = 0; + emu->sw.f.F87_C2 = 0; + emu->sw.f.F87_C3 = 0; } else if (isgreater(ST0.d, b)) { emu->sw.f.F87_C0 = 0; emu->sw.f.F87_C2 = 0; @@ -100,6 +104,10 @@ static inline void fpu_fcomi(x64emu_t* emu, double b) SET_FLAG(F_CF); SET_FLAG(F_PF); SET_FLAG(F_ZF); + } else if ((b==-INFINITY) || (ST0.d==INFINITY)) { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_PF); + CLEAR_FLAG(F_ZF); } else if (isgreater(ST0.d, b)) { CLEAR_FLAG(F_CF); CLEAR_FLAG(F_PF); |