diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-02-19 14:50:01 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-02-20 20:25:21 +0100 |
| commit | 5d42d9212fde49278e0ad0167edd77755a2fbcd9 (patch) | |
| tree | 8d77c0d42c421f6c729f4c1cad65a5484629c900 /src | |
| parent | 4a1e05524affadab3ba5a75f79c115a0743e483f (diff) | |
| download | box64-5d42d9212fde49278e0ad0167edd77755a2fbcd9.tar.gz box64-5d42d9212fde49278e0ad0167edd77755a2fbcd9.zip | |
Improved convertion to/from 80bits double, and added BOX64_X87_NO80BITS to not handle them
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_db.c | 30 | ||||
| -rwxr-xr-x | src/emu/x87emu_private.c | 30 | ||||
| -rwxr-xr-x | src/include/debug.h | 1 | ||||
| -rwxr-xr-x | src/main.c | 7 | ||||
| -rw-r--r-- | src/tools/rcfile.c | 1 |
5 files changed, 59 insertions, 10 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_db.c b/src/dynarec/arm64/dynarec_arm64_db.c index b9d71080..e40cc71d 100644 --- a/src/dynarec/arm64/dynarec_arm64_db.c +++ b/src/dynarec/arm64/dynarec_arm64_db.c @@ -295,21 +295,33 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin STRx_U12(x5, ed, 0); STRH_U12(x6, ed, 8); } else { - if(ed!=x1) { - MOVx_REG(x1, ed); + if(box64_x87_no80bits) { + v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0); + VLDR64_U12(v1, ed, fixedaddress); + } else { + if(ed!=x1) { + MOVx_REG(x1, ed); + } + x87_do_push_empty(dyn, ninst, x3); + CALL(arm_fld, -1); } - x87_do_push_empty(dyn, ninst, x3); - CALL(arm_fld, -1); } break; case 7: INST_NAME("FSTP tbyte"); - x87_forget(dyn, ninst, x1, x3, 0); - addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0); - if(ed!=x1) { - MOVx_REG(x1, ed); + if(box64_x87_no80bits) { + v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D); + addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0); + VSTR64_U12(v1, wback, fixedaddress); + } else { + x87_forget(dyn, ninst, x1, x3, 0); + addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0); + if(ed!=x1) { + MOVx_REG(x1, ed); + } + CALL(arm_fstp, -1); } - CALL(arm_fstp, -1); x87_do_pop(dyn, ninst, x3); break; default: diff --git a/src/emu/x87emu_private.c b/src/emu/x87emu_private.c index 2114c00d..9f4b8af6 100755 --- a/src/emu/x87emu_private.c +++ b/src/emu/x87emu_private.c @@ -83,6 +83,10 @@ void fpu_fbld(x64emu_t* emu, uint8_t* s) { // long double (80bits) -> double (64bits) void LD2D(void* ld, void* d) { + if(box64_x87_no80bits) { + *(uint64_t*)d = *(uint64_t*)ld; + return; + } FPU_t result; #pragma pack(push, 1) struct { @@ -122,7 +126,7 @@ void LD2D(void* ld, void* d) *(uint64_t*)d = result.q; return; } - if(((uint32_t)(val.b&0x7fff)==0) || (exp64<=0)) { + if(((uint32_t)(val.b&0x7fff)==0) || (exp64<-1074)) { //if(val.f.q==0) // zero //if(val.f.q!=0) @@ -134,6 +138,18 @@ void LD2D(void* ld, void* d) return; } + if(exp64<=0 && val.f.q) { + // try to see if it can be a denormal + int one = -exp64-1022; + uint64_t r = 0; + if(val.b&0x8000) + r |= 0x8000000000000000L; + r |= val.f.q>>one; + *(uint64_t*)d = r; + return; + + } + if(exp64>=0x7ff) { // to big value... result.d = HUGE_VAL; @@ -154,6 +170,10 @@ void LD2D(void* ld, void* d) // double (64bits) -> long double (80bits) void D2LD(void* d, void* ld) { + if(box64_x87_no80bits) { + *(uint64_t*)ld = *(uint64_t*)d; + return; + } #pragma pack(push, 1) struct { FPU_t f; @@ -190,6 +210,12 @@ void D2LD(void* d, void* ld) if(exp80!=0){ mant80final |= 0x8000000000000000L; exp80final += (BIAS80 - BIAS64); + } else if(mant80final!=0) { + // denormals -> normal + exp80final = BIAS80-1023; + int one = __builtin_clz(mant80final) + 1; + exp80final -= one; + mant80final<<=one; } } val.b = ((int16_t)(sign80)<<15)| (int16_t)(exp80final); @@ -201,6 +227,8 @@ void D2LD(void* d, void* ld) double FromLD(void* ld) { + if(box64_x87_no80bits) + return *(double*)ld; double ret; // cannot add = 0; it break factorio (issue when calling fmodl) LD2D(ld, &ret); return ret; diff --git a/src/include/debug.h b/src/include/debug.h index 0a6f722e..024805a1 100755 --- a/src/include/debug.h +++ b/src/include/debug.h @@ -48,6 +48,7 @@ extern int box64_nosandbox; extern int box64_malloc_hack; extern int box64_dummy_crashhandler; extern int box64_sse_flushto0; +extern int box64_x87_no80bits; extern int allow_missing_libs; extern int box64_mapclean; extern int box64_prefer_wrapped; diff --git a/src/main.c b/src/main.c index 4c0af6cd..ea809e54 100755 --- a/src/main.c +++ b/src/main.c @@ -93,6 +93,7 @@ int allow_missing_libs = 0; int box64_prefer_emulated = 0; int box64_prefer_wrapped = 0; int box64_sse_flushto0 = 0; +int box64_x87_no80bits = 0; int fix_64bit_inodes = 0; int box64_dummy_crashhandler = 1; int box64_mapclean = 0; @@ -965,6 +966,12 @@ void LoadEnvVars(box64context_t *context) printf_log(LOG_INFO, "BOX64: Direct apply of SSE Flush to 0 flag\n"); } } + if(getenv("BOX64_X87_NO80BITS")) { + if (strcmp(getenv("BOX64_X87_NO80BITS"), "1")==0) { + box64_x87_no80bits = 1; + printf_log(LOG_INFO, "BOX64: all 80bits x87 long double will be handle as double\n"); + } + } if(getenv("BOX64_PREFER_WRAPPED")) { if (strcmp(getenv("BOX64_PREFER_WRAPPED"), "1")==0) { box64_prefer_wrapped = 1; diff --git a/src/tools/rcfile.c b/src/tools/rcfile.c index 8a2ac920..75df7137 100644 --- a/src/tools/rcfile.c +++ b/src/tools/rcfile.c @@ -64,6 +64,7 @@ ENTRYBOOL(BOX64_X11THREADS, box64_x11threads) \ ENTRYBOOL(BOX64_X11GLX, box64_x11glx) \ ENTRYDSTRING(BOX64_LIBGL, box64_libGL) \ ENTRYBOOL(BOX64_SSE_FLUSHTO0, box64_sse_flushto0) \ +ENTRYBOOL(BOX64_X87_NO80BITS, box64_x87_no80bits) \ ENTRYSTRING_(BOX64_EMULATED_LIBS, emulated_libs) \ ENTRYBOOL(BOX64_ALLOWMISSINGLIBS, allow_missing_libs) \ ENTRYBOOL(BOX64_PREFER_WRAPPED, box64_prefer_wrapped) \ |