diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2024-10-08 16:53:18 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-08 10:53:18 +0200 |
| commit | 65adf2a860c0fd5e8ac5eed6c25726c610f268ae (patch) | |
| tree | 5db27b29acf65052f2261cc1d9bb2b943d8324e8 /src | |
| parent | dea6906ae9582376da5338feafdce63cace30420 (diff) | |
| download | box64-65adf2a860c0fd5e8ac5eed6c25726c610f268ae.tar.gz box64-65adf2a860c0fd5e8ac5eed6c25726c610f268ae.zip | |
[RV64_DYNAREC] Fixed CVTSS2SD and CVTSD2SS opcodes (#1913)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_f20f.c | 12 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_f30f.c | 10 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.c | 37 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 55 |
4 files changed, 83 insertions, 31 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_f20f.c b/src/dynarec/rv64/dynarec_rv64_f20f.c index 73fea164..373541f0 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f.c @@ -238,9 +238,15 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x5A: INST_NAME("CVTSD2SS Gx, Ex"); nextop = F8; - GETEXSD(v1, 0); - GETGXSS_empty(v0); - FCVTSD(v0, v1); + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + if (MODREG && gd == (nextop & 7) + (rex.b << 3)) { + v0 = sse_get_reg_size_changed(dyn, ninst, x2, gd, 1); + FCVTSD(v0, v0); + } else { + GETEXSD(v1, 0); + GETGXSS_empty(v0); + FCVTSD(v0, v1); + } break; case 0x5C: INST_NAME("SUBSD Gx, Ex"); diff --git a/src/dynarec/rv64/dynarec_rv64_f30f.c b/src/dynarec/rv64/dynarec_rv64_f30f.c index 7401d717..29438f2f 100644 --- a/src/dynarec/rv64/dynarec_rv64_f30f.c +++ b/src/dynarec/rv64/dynarec_rv64_f30f.c @@ -221,9 +221,15 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x5A: INST_NAME("CVTSS2SD Gx, Ex"); nextop = F8; + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); GETEXSS(v1, 0); - GETGXSD_empty(v0); - FCVTDS(v0, v1); + if (MODREG && gd == (nextop & 7) + (rex.b << 3)) { + v0 = sse_get_reg_size_changed(dyn, ninst, x2, gd, 0); + FCVTDS(v0, v0); + } else { + GETGXSD_empty(v0); + FCVTDS(v0, v1); + } break; case 0x5C: INST_NAME("SUBSS Gx, Ex"); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 7c572092..3dbe24f2 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -1701,6 +1701,43 @@ int sse_get_reg_empty(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single) return dyn->e.ssecache[a].reg; } +// get an ext register for an SSE reg which changes size, with single or not AFTER the change +int sse_get_reg_size_changed(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single) +{ + if (dyn->e.ssecache[a].v != -1) { + if (dyn->e.ssecache[a].vector == 1) { + // it's in the fpu, forget it first... + sse_forget_reg_vector(dyn, ninst, s1, a); + // update olds after the forget... + dyn->e.olds[a].changed = 1; + dyn->e.olds[a].purged = 0; + return sse_get_reg_size_changed(dyn, ninst, s1, a, single); + } + + // forget / reload if change of size + if (dyn->e.ssecache[a].single == single) { + sse_forget_reg(dyn, ninst, s1, a); + return sse_get_reg_size_changed(dyn, ninst, s1, a, single); + } + dyn->e.olds[a].changed = 1; + dyn->e.olds[a].purged = 0; + dyn->e.olds[a].type = !single; + dyn->e.ssecache[a].single = single; + dyn->e.ssecache[a].vector = 0; + dyn->e.extcache[EXTIDX(dyn->e.ssecache[a].reg)].t = single ? EXT_CACHE_SS : EXT_CACHE_SD; + return dyn->e.ssecache[a].reg; + } + dyn->e.ssecache[a].reg = fpu_get_reg_xmm(dyn, single ? EXT_CACHE_SS : EXT_CACHE_SD, a); + int ret = dyn->e.ssecache[a].reg; + dyn->e.ssecache[a].single = single; + dyn->e.ssecache[a].vector = 0; + if (!single) // load happens before size changed + FLW(dyn->e.ssecache[a].reg, xEmu, offsetof(x64emu_t, xmm[a])); + else + FLD(dyn->e.ssecache[a].reg, xEmu, offsetof(x64emu_t, xmm[a])); + return ret; +} + // forget ext register for a SSE reg, does nothing if the regs is not loaded void sse_forget_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a) { diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index d6380ea7..7e6f5e83 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1246,32 +1246,33 @@ void* rv64_next(x64emu_t* emu, uintptr_t addr); #define emit_pf STEPNAME(emit_pf) -#define x87_do_push STEPNAME(x87_do_push) -#define x87_do_push_empty STEPNAME(x87_do_push_empty) -#define x87_do_pop STEPNAME(x87_do_pop) -#define x87_get_current_cache STEPNAME(x87_get_current_cache) -#define x87_get_cache STEPNAME(x87_get_cache) -#define x87_get_extcache STEPNAME(x87_get_extcache) -#define x87_get_st STEPNAME(x87_get_st) -#define x87_get_st_empty STEPNAME(x87_get_st) -#define x87_free STEPNAME(x87_free) -#define x87_refresh STEPNAME(x87_refresh) -#define x87_forget STEPNAME(x87_forget) -#define x87_reget_st STEPNAME(x87_reget_st) -#define x87_stackcount STEPNAME(x87_stackcount) -#define x87_unstackcount STEPNAME(x87_unstackcount) -#define x87_swapreg STEPNAME(x87_swapreg) -#define x87_setround STEPNAME(x87_setround) -#define x87_restoreround STEPNAME(x87_restoreround) -#define sse_setround STEPNAME(sse_setround) -#define mmx_get_reg STEPNAME(mmx_get_reg) -#define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty) -#define mmx_forget_reg STEPNAME(mmx_forget_reg) -#define sse_get_reg STEPNAME(sse_get_reg) -#define sse_get_reg_empty STEPNAME(sse_get_reg_empty) -#define sse_forget_reg STEPNAME(sse_forget_reg) -#define sse_purge07cache STEPNAME(sse_purge07cache) -#define sse_reflect_reg STEPNAME(sse_reflect_reg) +#define x87_do_push STEPNAME(x87_do_push) +#define x87_do_push_empty STEPNAME(x87_do_push_empty) +#define x87_do_pop STEPNAME(x87_do_pop) +#define x87_get_current_cache STEPNAME(x87_get_current_cache) +#define x87_get_cache STEPNAME(x87_get_cache) +#define x87_get_extcache STEPNAME(x87_get_extcache) +#define x87_get_st STEPNAME(x87_get_st) +#define x87_get_st_empty STEPNAME(x87_get_st) +#define x87_free STEPNAME(x87_free) +#define x87_refresh STEPNAME(x87_refresh) +#define x87_forget STEPNAME(x87_forget) +#define x87_reget_st STEPNAME(x87_reget_st) +#define x87_stackcount STEPNAME(x87_stackcount) +#define x87_unstackcount STEPNAME(x87_unstackcount) +#define x87_swapreg STEPNAME(x87_swapreg) +#define x87_setround STEPNAME(x87_setround) +#define x87_restoreround STEPNAME(x87_restoreround) +#define sse_setround STEPNAME(sse_setround) +#define mmx_get_reg STEPNAME(mmx_get_reg) +#define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty) +#define mmx_forget_reg STEPNAME(mmx_forget_reg) +#define sse_get_reg STEPNAME(sse_get_reg) +#define sse_get_reg_empty STEPNAME(sse_get_reg_empty) +#define sse_get_reg_size_changed STEPNAME(sse_get_reg_size_changed) +#define sse_forget_reg STEPNAME(sse_forget_reg) +#define sse_purge07cache STEPNAME(sse_purge07cache) +#define sse_reflect_reg STEPNAME(sse_reflect_reg) #define sse_get_reg_empty_vector STEPNAME(sse_get_reg_empty_vector) #define sse_get_reg_vector STEPNAME(sse_get_reg_vector) @@ -1499,6 +1500,8 @@ int sse_get_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single); int sse_get_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int forwrite, int sew); // get float register for a SSE reg, but don't try to synch it if it needed to be created int sse_get_reg_empty(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single); +// get an ext register for an SSE reg which changes size, with single or not AFTER the change +int sse_get_reg_size_changed(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single); // get rvv register for an SSE reg, but don't try to synch it if it needed to be created int sse_get_reg_empty_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a); // forget float register for a SSE reg, create the entry if needed |