From 90ce6e5ed2349d13cabeb42b087821cf97d2ebd6 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 11 Nov 2026 00:50:45 +0800 Subject: [PATCH] [RV64_DYNAREC] Restore cached MMX state at loop back-edges --- src/dynarec/rv64/dynarec_rv64_functions.c | 4 ++-- src/dynarec/rv64/dynarec_rv64_helper.c | 11 +++++++++++ src/dynarec/rv64/dynarec_rv64_pass0.h | 2 +- src/dynarec/rv64/dynarec_rv64_pass1.h | 2 +- src/dynarec/rv64/dynarec_rv64_private.h | 2 +- 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c index 15d94a2888..99248f9eaf 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.c +++ b/src/dynarec/rv64/dynarec_rv64_functions.c @@ -433,7 +433,7 @@ void extcacheUnwind(extcache_t* cache) { if (!cache->swapped && !cache->news && !cache->stack_push && !cache->stack_pop) { int dirty = 0; - for (int i = 0; i < 16; ++i) + for (int i = 0; i < 24; ++i) if (cache->olds[i].v) { dirty = 1; break; @@ -473,7 +473,7 @@ void extcacheUnwind(extcache_t* cache) cache->news = 0; } // add/change bad regs - for (int i = 0; i < 16; ++i) { + for (int i = 0; i < 24; ++i) { if (cache->olds[i].v) { cache->extcache[i] = cache->olds[i]; // the undo log has been applied, don't reapply it on a second unwind diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index d8ff10f652..cbbe4b16a5 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -1537,6 +1537,15 @@ void fpu_borrow_regs(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int* regs, } } +static void mmx_save_old(dynarec_rv64_t* dyn, int idx) +{ + if (dyn->e.news & (1u << idx)) + return; + if (dyn->e.olds[idx].v) + return; + dyn->e.olds[idx] = dyn->e.extcache[idx]; +} + void mmx_flush_reg_preserve_vtype(dynarec_rv64_t* dyn, int ninst, int s1, int a) { if (dyn->e.mmxcache[a].v == -1) @@ -1549,6 +1558,7 @@ void mmx_flush_reg_preserve_vtype(dynarec_rv64_t* dyn, int ninst, int s1, int a) vector_restore_vtype(dyn, ninst, s1, sew, vlmul, vl); } FSD(dyn->e.mmxcache[a].reg, xEmu, offsetof(x64emu_t, mmx[a])); + mmx_save_old(dyn, EXTIDX(dyn->e.mmxcache[a].reg)); fpu_free_reg(dyn, dyn->e.mmxcache[a].reg); dyn->e.mmxcache[a].v = -1; return; @@ -1559,6 +1569,7 @@ static void mmx_transfer_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a) if (dyn->e.mmxcache[a].v == -1) return; + mmx_save_old(dyn, EXTIDX(dyn->e.mmxcache[a].reg)); uint8_t sew, vlmul, vl; vector_save_vtype(dyn, &sew, &vlmul, &vl); vector_vsetvli(dyn, ninst, s1, VECTOR_SEW64, VECTOR_LMUL1, 1); diff --git a/src/dynarec/rv64/dynarec_rv64_pass0.h b/src/dynarec/rv64/dynarec_rv64_pass0.h index e8186bfc2d..4924afab63 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass0.h +++ b/src/dynarec/rv64/dynarec_rv64_pass0.h @@ -76,7 +76,7 @@ dyn->e.combined1 = dyn->e.combined2 = 0; \ dyn->e.swapped = 0; \ dyn->e.barrier = 0; \ - for (int i = 0; i < 16; ++i) \ + for (int i = 0; i < 24; ++i) \ dyn->e.olds[i].v = 0; \ dyn->insts[ninst].f_entry = dyn->f; \ dyn->insts[ninst].vector_sew_entry = dyn->vector_sew; \ diff --git a/src/dynarec/rv64/dynarec_rv64_pass1.h b/src/dynarec/rv64/dynarec_rv64_pass1.h index 9505ea0a80..abc6dd8230 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass1.h +++ b/src/dynarec/rv64/dynarec_rv64_pass1.h @@ -10,7 +10,7 @@ #define NEW_INST \ dyn->insts[ninst].f_entry = dyn->f; \ dyn->e.combined1 = dyn->e.combined2 = 0; \ - for (int i = 0; i < 16; ++i) \ + for (int i = 0; i < 24; ++i) \ dyn->e.olds[i].v = 0; \ dyn->insts[ninst].vector_sew_entry = dyn->vector_sew; \ dyn->inst_sew = dyn->vector_sew; \ diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index 0217f0e30f..024164712b 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -69,7 +69,7 @@ typedef struct extcache_s { uint8_t pushed; // positive pushed value (to check for overflow) uint8_t poped; // positive poped value (to check for underflow) uint32_t news; // bitmask, wich neoncache are new for this opcode - ext_cache_t olds[16]; // SSE caches descriptors changed or removed by this instruction + ext_cache_t olds[24]; // cache descriptors changed or removed by this instruction // fpu cache int8_t x87cache[8]; // cache status for the 8 x87 register behind the fpu stack int8_t x87reg[8]; // reg used for x87cache entry