From e0f9785c59f39761499e4d3b25f7945dfc35ed29 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 12 Nov 2026 20:31:43 +0800 Subject: [PATCH 1/4] [ARM64_DYNAREC] Fixed wrongly skipped dirty xmm registers This is the same fix as #4697 (LA64) or #4694 (RV64), but in the Arm DynaRec way. --- src/dynarec/arm64/dynarec_arm64_functions.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_functions.c b/src/dynarec/arm64/dynarec_arm64_functions.c index e61a44452c..165ad10859 100644 --- a/src/dynarec/arm64/dynarec_arm64_functions.c +++ b/src/dynarec/arm64/dynarec_arm64_functions.c @@ -1590,6 +1590,7 @@ void addSSEPreload(dynarec_arm_t* dyn, int ninst, int i2, uint32_t preload) has_host_call = 1; } uint16_t ymm_mask = 0; + uint16_t xmm_mask = 0; for(int i=0; i<16; ++i) { if(preload&(1<insts[i3].n.ssecache[i].reg = v; dyn->insts[i3].n.neoncache[v].t = NEON_CACHE_XMMR; dyn->insts[i3].n.neoncache[v].n = i; + if (i3 == i2) xmm_mask |= 1 << i; ++i3; } } @@ -1625,10 +1627,10 @@ void addSSEPreload(dynarec_arm_t* dyn, int ninst, int i2, uint32_t preload) } } } - preload = (preload&0xffff) | (ymm_mask<<16); // update ymm_mask + preload = (xmm_mask & 0xffff) | (ymm_mask << 16); // update masks dyn->insts[i2].preload_xmmymm = preload; dyn->insts[i2].preload_from = ninst; dyn->insts[i2].preload_host_call = has_host_call; - dyn->insts[i2].n.xmm_unneeded |= preload&0xffff; + dyn->insts[i2].n.xmm_unneeded |= xmm_mask; dyn->insts[i2].n.ymm_unneeded |= ymm_mask; } From a9893af3a62ad05aff6fdd0f612a6f9cccb74d15 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 12 Nov 2026 20:50:21 +0800 Subject: [PATCH 2/4] same for ymm --- src/dynarec/arm64/dynarec_arm64_functions.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_functions.c b/src/dynarec/arm64/dynarec_arm64_functions.c index 165ad10859..05b57ebf43 100644 --- a/src/dynarec/arm64/dynarec_arm64_functions.c +++ b/src/dynarec/arm64/dynarec_arm64_functions.c @@ -1611,8 +1611,7 @@ void addSSEPreload(dynarec_arm_t* dyn, int ninst, int i2, uint32_t preload) } if(preload&(1<<(16+i))) { int v = ymm_preload_reg(dyn, i2?(i2-1):0, ninst, i); - if(v!=-1) { - ymm_mask |= 1<insts[i3].n.neoncache[v].t = NEON_CACHE_YMMR; dyn->insts[i3].n.neoncache[v].n = i; + if (i3 == i2) ymm_mask |= 1 << i; ++i3; } } From dcb030ac5a44e1f2a28472005db23663c41f3491 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Fri, 13 Nov 2026 00:30:43 +0800 Subject: [PATCH 3/4] we should record the removal in ymm_removed and ymm_regs. --- src/dynarec/arm64/dynarec_arm64_helper.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index 3ed5deb797..ba27d97067 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -2815,7 +2815,7 @@ int fpu_get_reg_ymm(dynarec_arm_t* dyn, int ninst, int t, int ymm, int k1, int k if(!dyn->n.fpuused[i+j]) { // should a test be done to check if ymm is already in the purge list? if(!is_ymm_to_keep(dyn, i+j, k1, k2, k3) && (dyn->n.neoncache[i+j].t==NEON_CACHE_YMMR)) { - dyn->n.neoncache[i+j].v = 0; + fpu_free_reg(dyn, i+j); int ret = internal_mark_ymm(dyn, t, ymm, i+j); if(ret>=0) return ret; } @@ -2824,7 +2824,7 @@ int fpu_get_reg_ymm(dynarec_arm_t* dyn, int ninst, int t, int ymm, int k1, int k i = SCRATCH0; for(int j=dyn->n.fpu_scratch; j<8; ++j) { if(!is_ymm_to_keep(dyn, i+j, k1, k2, k3) && (dyn->n.neoncache[i+j].t==NEON_CACHE_YMMR)) { - dyn->n.neoncache[i+j].v = 0; + fpu_free_reg(dyn, i+j); int ret = internal_mark_ymm(dyn, t, ymm, i+j); if(ret>=0) return ret; } @@ -2836,7 +2836,7 @@ int fpu_get_reg_ymm(dynarec_arm_t* dyn, int ninst, int t, int ymm, int k1, int k // Save the reg and recycle it dyn->n.ymm_used|=(1<n.neoncache[i+j].n); VSTR128_U12(i+j, xEmu, offsetof(x64emu_t, ymm[dyn->n.neoncache[i+j].n])); - dyn->n.neoncache[i+j].v = 0; + fpu_free_reg(dyn, i+j); int ret = internal_mark_ymm(dyn, t, ymm, i+j); if(ret>=0) return ret; } @@ -2849,7 +2849,7 @@ int fpu_get_reg_ymm(dynarec_arm_t* dyn, int ninst, int t, int ymm, int k1, int k if((dyn->n.neoncache[i+j].t==NEON_CACHE_YMMW) && !is_ymm_to_keep(dyn, i+j, k1, k2, k3)) { dyn->n.ymm_used|=(1<n.neoncache[i+j].n); VSTR128_U12(i+j, xEmu, offsetof(x64emu_t, ymm[dyn->n.neoncache[i+j].n])); - dyn->n.neoncache[i+j].v = 0; + fpu_free_reg(dyn, i+j); int ret = internal_mark_ymm(dyn, t, ymm, i+j); if(ret>=0) return ret; } From e378a2ac413b458707bd1e896095552b8997be63 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Fri, 13 Nov 2026 00:36:53 +0800 Subject: [PATCH 4/4] typo --- src/dynarec/arm64/dynarec_arm64_functions.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dynarec/arm64/dynarec_arm64_functions.c b/src/dynarec/arm64/dynarec_arm64_functions.c index 05b57ebf43..64fbeb4c08 100644 --- a/src/dynarec/arm64/dynarec_arm64_functions.c +++ b/src/dynarec/arm64/dynarec_arm64_functions.c @@ -1590,6 +1590,7 @@ void addSSEPreload(dynarec_arm_t* dyn, int ninst, int i2, uint32_t preload) has_host_call = 1; } uint16_t ymm_mask = 0; + uint16_t ymm_preload = 0; uint16_t xmm_mask = 0; for(int i=0; i<16; ++i) { if(preload&(1<insts[i2].preload_xmmymm = preload; dyn->insts[i2].preload_from = ninst; dyn->insts[i2].preload_host_call = has_host_call;