diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2025-03-18 04:58:29 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-17 21:58:29 +0100 |
| commit | 546238681eb8d5b3d80cf1d77075dcbff82de72a (patch) | |
| tree | 7bb747bde4005a9742f48f29122858cfaf948fa4 /src | |
| parent | 87327b182f6fd6eefd2620e0b1775e3fedd33459 (diff) | |
| download | box64-546238681eb8d5b3d80cf1d77075dcbff82de72a.tar.gz box64-546238681eb8d5b3d80cf1d77075dcbff82de72a.zip | |
[RV64_DYNAREC] More minor changes and fixes to x87 opcodes (#2443)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_da.c | 36 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_db.c | 66 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_dd.c | 11 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.c | 37 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 4 |
5 files changed, 63 insertions, 91 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_da.c b/src/dynarec/rv64/dynarec_rv64_da.c index 165ae3c8..97058a60 100644 --- a/src/dynarec/rv64/dynarec_rv64_da.c +++ b/src/dynarec/rv64/dynarec_rv64_da.c @@ -45,14 +45,7 @@ uintptr_t dynarec64_DA(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni if (MODREG) switch (nextop) { - case 0xC0: - case 0xC1: - case 0xC2: - case 0xC3: - case 0xC4: - case 0xC5: - case 0xC6: - case 0xC7: + case 0xC0 ... 0xC7: INST_NAME("FCMOVB ST0, STx"); READFLAGS(X_CF); v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7)); @@ -64,14 +57,7 @@ uintptr_t dynarec64_DA(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni else FMVD(v1, v2); break; - case 0xC8: - case 0xC9: - case 0xCA: - case 0xCB: - case 0xCC: - case 0xCD: - case 0xCE: - case 0xCF: + case 0xC8 ... 0xCF: INST_NAME("FCMOVE ST0, STx"); READFLAGS(X_ZF); v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7)); @@ -83,14 +69,7 @@ uintptr_t dynarec64_DA(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni else FMVD(v1, v2); break; - case 0xD0: - case 0xD1: - case 0xD2: - case 0xD3: - case 0xD4: - case 0xD5: - case 0xD6: - case 0xD7: + case 0xD0 ... 0xD7: INST_NAME("FCMOVBE ST0, STx"); READFLAGS(X_CF | X_ZF); v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7)); @@ -102,14 +81,7 @@ uintptr_t dynarec64_DA(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni else FMVD(v1, v2); break; - case 0xD8: - case 0xD9: - case 0xDA: - case 0xDB: - case 0xDC: - case 0xDD: - case 0xDE: - case 0xDF: + case 0xD8 ... 0xDF: INST_NAME("FCMOVU ST0, STx"); READFLAGS(X_PF); v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7)); diff --git a/src/dynarec/rv64/dynarec_rv64_db.c b/src/dynarec/rv64/dynarec_rv64_db.c index 45fcd1e0..3aa4b9b2 100644 --- a/src/dynarec/rv64/dynarec_rv64_db.c +++ b/src/dynarec/rv64/dynarec_rv64_db.c @@ -46,14 +46,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni if (MODREG) switch (nextop) { - case 0xC0: - case 0xC1: - case 0xC2: - case 0xC3: - case 0xC4: - case 0xC5: - case 0xC6: - case 0xC7: + case 0xC0 ... 0xC7: INST_NAME("FCMOVNB ST0, STx"); READFLAGS(X_CF); v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7)); @@ -66,14 +59,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni FMVD(v1, v2); // F_CF==0 } break; - case 0xC8: - case 0xC9: - case 0xCA: - case 0xCB: - case 0xCC: - case 0xCD: - case 0xCE: - case 0xCF: + case 0xC8 ... 0xCF: INST_NAME("FCMOVNE ST0, STx"); READFLAGS(X_ZF); v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7)); @@ -86,14 +72,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni FMVD(v1, v2); // F_ZF==0 } break; - case 0xD0: - case 0xD1: - case 0xD2: - case 0xD3: - case 0xD4: - case 0xD5: - case 0xD6: - case 0xD7: + case 0xD0 ... 0xD7: INST_NAME("FCMOVNBE ST0, STx"); READFLAGS(X_CF | X_ZF); v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7)); @@ -106,14 +85,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni FMVD(v1, v2); // F_CF==0 & F_ZF==0 } break; - case 0xD8: - case 0xD9: - case 0xDA: - case 0xDB: - case 0xDC: - case 0xDD: - case 0xDE: - case 0xDF: + case 0xD8 ... 0xDF: INST_NAME("FCMOVNU ST0, STx"); READFLAGS(X_PF); v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7)); @@ -143,14 +115,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni x87_purgecache(dyn, ninst, 0, x1, x2, x3); CALL(reset_fpu, -1, 0, 0); break; - case 0xE8: - case 0xE9: - case 0xEA: - case 0xEB: - case 0xEC: - case 0xED: - case 0xEE: - case 0xEF: + case 0xE8 ... 0xEF: INST_NAME("FUCOMI ST0, STx"); SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7)); @@ -162,14 +127,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; - case 0xF0: - case 0xF1: - case 0xF2: - case 0xF3: - case 0xF4: - case 0xF5: - case 0xF6: - case 0xF7: + case 0xF0 ... 0xF7: INST_NAME("FCOMI ST0, STx"); SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7)); @@ -234,12 +192,14 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } MARK2; SW(x4, wback, fixedaddress); + x87_restoreround(dyn, ninst, u8); X87_POP_OR_FAIL(dyn, ninst, x3); break; case 5: INST_NAME("FLD tbyte"); addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 8, 0); if ((PK(0) == 0xDB && ((PK(1) >> 3) & 7) == 7) || (!rex.is32bits && PK(0) >= 0x40 && PK(0) <= 0x4f && PK(1) == 0xDB && ((PK(2) >> 3) & 7) == 7)) { + NOTEST(x5); // the FLD is immediatly followed by an FSTP LD(x5, ed, fixedaddress + 0); LH(x6, ed, fixedaddress + 8); @@ -262,11 +222,9 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } else { ADDI(x1, ed, fixedaddress); X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, x3); - // sync top - s0 = x87_stackcount(dyn, ninst, x3); + x87_reflectcount(dyn, ninst, x3, x4); CALL(native_fld, -1, x1, 0); - // go back with the top & stack counter - x87_unstackcount(dyn, ninst, x3, s0); + x87_unreflectcount(dyn, ninst, x3, x4); } } break; @@ -279,9 +237,9 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } else { x87_forget(dyn, ninst, x1, x3, 0); addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0); - s0 = x87_stackcount(dyn, ninst, x3); + x87_reflectcount(dyn, ninst, x3, x4); CALL(native_fstp, -1, ed, 0); - x87_unstackcount(dyn, ninst, x3, s0); + x87_unreflectcount(dyn, ninst, x3, x4); } X87_POP_OR_FAIL(dyn, ninst, x3); break; diff --git a/src/dynarec/rv64/dynarec_rv64_dd.c b/src/dynarec/rv64/dynarec_rv64_dd.c index 4a1e527d..c21030ca 100644 --- a/src/dynarec/rv64/dynarec_rv64_dd.c +++ b/src/dynarec/rv64/dynarec_rv64_dd.c @@ -45,11 +45,20 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni if (MODREG) switch (nextop) { case 0xC0 ... 0xC7: - INST_NAME("FFREE STx"); +#if 1 + if ((nextop & 7) == 0 && PK(0) == 0xD9 && PK(1) == 0xF7) { + MESSAGE(LOG_DUMP, "Hack for FFREE ST0 / FINCSTP\n"); + x87_do_pop(dyn, ninst, x1); + addr += 2; + SKIPTEST(x1); + } else + x87_free(dyn, ninst, x1, x2, x3, nextop & 7); +#else MESSAGE(LOG_DUMP, "Need Optimization\n"); x87_purgecache(dyn, ninst, 0, x1, x2, x3); MOV32w(x1, nextop & 7); CALL(fpu_do_free, -1, x1, 0); +#endif break; case 0xD0 ... 0xD7: INST_NAME("FST ST0, STx"); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 4f3286fa..31b35811 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -1166,6 +1166,35 @@ void x87_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1, int s2, in MESSAGE(LOG_DUMP, "\t---Purge x87 Cache and Synch Stackcount\n"); } + +void x87_reflectcount(dynarec_rv64_t* dyn, int ninst, int s1, int s2) +{ + // Synch top and stack count + int a = dyn->e.x87stack; + if (a) { + MESSAGE(LOG_DUMP, "\tSync x87 Count of %d-----\n", a); + // Add x87stack to emu fpu_stack + LW(s2, xEmu, offsetof(x64emu_t, fpu_stack)); + ADDI(s2, s2, a); + SW(s2, xEmu, offsetof(x64emu_t, fpu_stack)); + // Sub x87stack to top, with and 7 + LW(s2, xEmu, offsetof(x64emu_t, top)); + SUBI(s2, s2, a); + ANDI(s2, s2, 7); + SW(s2, xEmu, offsetof(x64emu_t, top)); + // update tags + LH(s1, xEmu, offsetof(x64emu_t, fpu_tags)); + if (a > 0) { + SLLI(s1, s1, a * 2); + } else { + MOV32w(s2, 0xffff0000); + OR(s1, s1, s2); + SRLI(s1, s1, -a * 2); + } + SH(s1, xEmu, offsetof(x64emu_t, fpu_tags)); + } +} + static void x87_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3) { // Sync top and stack count @@ -1221,7 +1250,7 @@ static void x87_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int } } -static void x87_unreflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3) +void x87_unreflectcount(dynarec_rv64_t* dyn, int ninst, int s1, int s2) { // revert top and stack count int a = dyn->e.x87stack; @@ -1238,8 +1267,8 @@ static void x87_unreflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, i // update tags LH(s1, xEmu, offsetof(x64emu_t, fpu_tags)); if (a > 0) { - MOV32w(s3, 0xffff0000); - OR(s1, s1, s3); + MOV32w(s2, 0xffff0000); + OR(s1, s1, s2); SRLI(s1, s1, a * 2); } else { SLLI(s1, s1, -a * 2); @@ -2847,7 +2876,7 @@ void fpu_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3) void fpu_unreflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3) { // need to undo the top and stack tracking that must not be reflected permanently yet - x87_unreflectcache(dyn, ninst, s1, s2, s3); + x87_unreflectcount(dyn, ninst, s1, s2); } void emit_pf(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 1183feb7..684357bf 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1391,6 +1391,8 @@ void* rv64_next(void); #define sse_purgecache STEPNAME(sse_purgecache) #define fpu_reflectcache STEPNAME(fpu_reflectcache) #define fpu_unreflectcache STEPNAME(fpu_unreflectcache) +#define x87_reflectcount STEPNAME(x87_reflectcount) +#define x87_unreflectcount STEPNAME(x87_unreflectcount) #define avx_purge_ymm STEPNAME(avx_purge_ymm) #define CacheTransform STEPNAME(CacheTransform) @@ -1647,6 +1649,8 @@ void mmx_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1); void x87_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1, int s2, int s3); void fpu_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3); void fpu_unreflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3); +void x87_reflectcount(dynarec_rv64_t* dyn, int ninst, int s1, int s2); +void x87_unreflectcount(dynarec_rv64_t* dyn, int ninst, int s1, int s2); void fpu_pushcache(dynarec_rv64_t* dyn, int ninst, int s1, int not07); void fpu_popcache(dynarec_rv64_t* dyn, int ninst, int s1, int not07); |