diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2025-03-29 10:04:19 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2025-03-29 10:04:19 +0100 |
| commit | e7b71cba5fe8ef92cc50266ed380203b7b2ed4ef (patch) | |
| tree | e307f89f7a5986dc617727a0dd2933a19c6d513f /src | |
| parent | d2817e72468bf460c8758f6ee6bdd804cf317f90 (diff) | |
| download | box64-e7b71cba5fe8ef92cc50266ed380203b7b2ed4ef.tar.gz box64-e7b71cba5fe8ef92cc50266ed380203b7b2ed4ef.zip | |
[ARM64_DYNAREC] Fixed a potential issue with SSE regs when internal jumping to a native call
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_functions.c | 21 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_private.h | 6 |
2 files changed, 24 insertions, 3 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_functions.c b/src/dynarec/arm64/dynarec_arm64_functions.c index dbc084dd..6b8013af 100644 --- a/src/dynarec/arm64/dynarec_arm64_functions.c +++ b/src/dynarec/arm64/dynarec_arm64_functions.c @@ -65,6 +65,8 @@ void fpu_reset_scratch(dynarec_arm_t* dyn) dyn->n.ymm_regs = 0; dyn->n.ymm_write = 0; dyn->n.ymm_removed = 0; + dyn->n.xmm_write = 0; + dyn->n.xmm_removed = 0; } // Get a x87 double reg int fpu_get_reg_x87(dynarec_arm_t* dyn, int ninst, int t, int n) @@ -96,6 +98,11 @@ void fpu_free_reg(dynarec_arm_t* dyn, int reg) else dyn->n.ymm_regs |= ((uint64_t)(reg-EMM0))<<(dyn->n.neoncache[reg].n*4); } + if(dyn->n.neoncache[reg].t==NEON_CACHE_XMMR || dyn->n.neoncache[reg].t==NEON_CACHE_XMMW) { + dyn->n.xmm_removed |= 1<<dyn->n.neoncache[reg].n; + if(dyn->n.neoncache[reg].t==NEON_CACHE_XMMW) + dyn->n.xmm_write |= 1<<dyn->n.neoncache[reg].n; + } if(dyn->n.neoncache[reg].t!=NEON_CACHE_ST_F && dyn->n.neoncache[reg].t!=NEON_CACHE_ST_D && dyn->n.neoncache[reg].t!=NEON_CACHE_ST_I64) dyn->n.neoncache[reg].v = 0; if(dyn->n.fpu_scratch && reg==SCRATCH0+dyn->n.fpu_scratch-1) @@ -174,6 +181,8 @@ static void fpu_reset_reg_neoncache(neoncache_t* n) n->ymm_removed = 0; n->ymm_used = 0; n->ymm_write = 0; + n->xmm_removed = 0; + n->xmm_write = 0; } void fpu_reset_reg(dynarec_arm_t* dyn) @@ -578,7 +587,17 @@ void neoncacheUnwind(neoncache_t* cache) cache->fpuused[i] = 0; } } - // add back removed YMM + // add back removed XMM + if(cache->xmm_removed) { + for(int i=0; i<16; ++i) + if(cache->xmm_removed&(1<<i)) { + int reg = (i<8)?(XMM0+i):(XMM8+i-8); + cache->neoncache[reg].t = (cache->xmm_write&(1<<i))?NEON_CACHE_XMMW:NEON_CACHE_XMMR; + cache->neoncache[reg].n = i; + } + cache->xmm_write = cache->xmm_removed = 0; + } + // add back removed YMM if(cache->ymm_removed) { for(int i=0; i<16; ++i) if(cache->ymm_removed&(1<<i)) { diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h index b88a9ad1..740e7e9e 100644 --- a/src/dynarec/arm64/dynarec_arm64_private.h +++ b/src/dynarec/arm64/dynarec_arm64_private.h @@ -72,10 +72,12 @@ typedef struct neoncache_s { int8_t mmxcount; // number of mmx register used (not both mmx and x87 at the same time) int8_t fpu_scratch; // scratch counter int8_t fpu_reg; // x87/sse/mmx reg counter + uint16_t xmm_write; // 1bit of xmmXX removed write + uint16_t xmm_removed; // 1bit if xmmXX was removed uint16_t ymm_used; // mask of the ymm regs used in this opcode + uint16_t ymm_write; // 1bit of ymmXX removed write + uint16_t ymm_removed; // 1bit if ymmXX was removed uint64_t ymm_regs; // 4bits (0-15) position of 16 ymmXX regs removed - uint16_t ymm_write; // 1bits of ymmXX removed write - uint16_t ymm_removed; // 1bits if ymmXX was removed } neoncache_t; typedef struct flagcache_s { |