diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2025-02-06 17:58:48 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2025-02-06 17:58:48 +0100 |
| commit | 4c3d55fb5c10b7975c4510f96b0f6c2cc4d646b5 (patch) | |
| tree | 22afdcfa5178b202f6e63caafed0a0aba7ff7d99 | |
| parent | d2a5005dcc40b76762717daee9b482b201a7ac3c (diff) | |
| download | box64-4c3d55fb5c10b7975c4510f96b0f6c2cc4d646b5.tar.gz box64-4c3d55fb5c10b7975c4510f96b0f6c2cc4d646b5.zip | |
[ARM64_DYNAREC] Fixed fstp long double when fastround==0
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_db.c | 6 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.c | 40 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.h | 7 |
3 files changed, 48 insertions, 5 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_db.c b/src/dynarec/arm64/dynarec_arm64_db.c index 91d72634..0bcd3de6 100644 --- a/src/dynarec/arm64/dynarec_arm64_db.c +++ b/src/dynarec/arm64/dynarec_arm64_db.c @@ -309,10 +309,10 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, 0); // sync top - s0 = x87_stackcount(dyn, ninst, x3); + x87_reflectcount(dyn, ninst, x3, x4); CALL(native_fld, -1); // go back with the top & stack counter - x87_unstackcount(dyn, ninst, x3, s0); + x87_unreflectcount(dyn, ninst, x3, x4); } } break; @@ -327,7 +327,9 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin x87_forget(dyn, ninst, x1, x3, 0); addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0); if(ed!=x1) {MOVx_REG(x1, ed);} + x87_reflectcount(dyn, ninst, x3, x4); CALL(native_fstp, -1); + x87_unreflectcount(dyn, ninst, x3, x4); } else { // Painfully long, straight conversion from the C code, shoud be optimized v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D); diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index f7428872..313345e8 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -1188,7 +1188,41 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int } MESSAGE(LOG_DUMP, "\t---Purge x87 Cache and Synch Stackcount\n"); } - +void x87_reflectcount(dynarec_arm_t* dyn, int ninst, int s1, int s2) +{ + // Synch top & stack counter + int a = dyn->n.x87stack; + if(a) { + MESSAGE(LOG_DUMP, "\tSync x87 Count of %d-----\n", a); + // Add x87stack to emu fpu_stack + LDRw_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack)); + if(a>0) { + ADDw_U12(s2, s2, a); + } else { + SUBw_U12(s2, s2, -a); + } + STRw_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack)); + // Sub x87stack to top, with and 7 + LDRw_U12(s2, xEmu, offsetof(x64emu_t, top)); + if(a>0) { + SUBw_U12(s2, s2, a); + } else { + ADDw_U12(s2, s2, -a); + } + ANDw_mask(s2, s2, 0, 2); //mask=7 + STRw_U12(s2, xEmu, offsetof(x64emu_t, top)); + // update tags + LDRH_U12(s1, xEmu, offsetof(x64emu_t, fpu_tags)); + if(a>0) { + LSLw_IMM(s1, s1, a*2); + } else { + ORRw_mask(s1, s1, 0b010000, 0b001111); // 0xffff0000 + LSRw_IMM(s1, s1, -a*2); + } + STRH_U12(s1, xEmu, offsetof(x64emu_t, fpu_tags)); + MESSAGE(LOG_DUMP, "\t-----Sync x87 Count\n"); + } +} static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3) { // Synch top & stack counter @@ -1248,7 +1282,7 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int } } -static void x87_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3) +void x87_unreflectcount(dynarec_arm_t* dyn, int ninst, int s1, int s2) { // go back with the top & stack counter int a = dyn->n.x87stack; @@ -2504,7 +2538,7 @@ void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3) void fpu_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3) { // need to undo some things on the x87 tracking - x87_unreflectcache(dyn, ninst, s1, s2, s3); + x87_unreflectcount(dyn, ninst, s1, s2); } void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s4) diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index 91349ac9..f5a7104f 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -1404,6 +1404,8 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr); #define fpu_purgecache STEPNAME(fpu_purgecache) #define mmx_purgecache STEPNAME(mmx_purgecache) #define x87_purgecache STEPNAME(x87_purgecache) +#define x87_reflectcount STEPNAME(x87_reflectcount) +#define x87_unreflectcount STEPNAME(x87_unreflectcount) #define fpu_reflectcache STEPNAME(fpu_reflectcache) #define fpu_unreflectcache STEPNAME(fpu_unreflectcache) #define avx_purge_ymm STEPNAME(avx_purge_ymm) @@ -1641,6 +1643,11 @@ void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1); // purge x87 cache void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3); +// temporarily set x87 stack count for C functions +void x87_reflectcount(dynarec_arm_t* dyn, int ninst, int s1, int s2); +// restore count after +void x87_unreflectcount(dynarec_arm_t* dyn, int ninst, int s1, int s2); +// global fpu helper void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3); void fpu_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3); void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not07); |